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/object_utils.h b/src/object_utils.h
index 8b2aab9..d523ecc 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -32,29 +32,30 @@
class ObjectLock {
public:
- explicit ObjectLock(Object* object) : self_(Thread::Current()), obj_(object) {
+ explicit ObjectLock(Object* object) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
+ : self_(Thread::Current()), obj_(object) {
CHECK(object != NULL);
obj_->MonitorEnter(self_);
}
- ~ObjectLock() {
+ ~ObjectLock() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
obj_->MonitorExit(self_);
}
- void Wait() {
+ void Wait() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return Monitor::Wait(self_, obj_, 0, 0, false);
}
- void Notify() {
+ void Notify() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
obj_->Notify();
}
- void NotifyAll() {
+ void NotifyAll() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
obj_->NotifyAll();
}
private:
- Thread* self_;
+ Thread* const self_;
Object* obj_;
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
@@ -62,6 +63,7 @@
class ClassHelper {
public:
ClassHelper(const Class* c = NULL, ClassLinker* l = NULL)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
: class_def_(NULL),
class_linker_(l),
dex_cache_(NULL),
@@ -73,7 +75,8 @@
}
}
- void ChangeClass(const Class* new_c) {
+ void ChangeClass(const Class* new_c)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK(new_c != NULL) << "klass_=" << klass_; // Log what we were changing from if any
CHECK(new_c->IsClass()) << "new_c=" << new_c;
if (dex_cache_ != NULL) {
@@ -90,7 +93,7 @@
// The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
// If you need it longer, copy it into a std::string.
- const char* GetDescriptor() {
+ const char* GetDescriptor() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK(klass_ != NULL);
if (UNLIKELY(klass_->IsArrayClass())) {
return GetArrayDescriptor();
@@ -106,7 +109,7 @@
}
}
- const char* GetArrayDescriptor() {
+ const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
std::string result("[");
const Class* saved_klass = klass_;
CHECK(saved_klass != NULL);
@@ -117,7 +120,8 @@
return descriptor_.c_str();
}
- const DexFile::ClassDef* GetClassDef() {
+ const DexFile::ClassDef* GetClassDef()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile::ClassDef* result = class_def_;
if (result == NULL) {
result = GetDexFile().FindClassDef(GetDescriptor());
@@ -126,7 +130,7 @@
return result;
}
- uint32_t NumDirectInterfaces() {
+ uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DCHECK(klass_ != NULL);
if (klass_->IsPrimitive()) {
return 0;
@@ -144,14 +148,16 @@
}
}
- uint16_t GetDirectInterfaceTypeIdx(uint32_t idx) {
+ uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DCHECK(klass_ != NULL);
DCHECK(!klass_->IsPrimitive());
DCHECK(!klass_->IsArrayClass());
return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
}
- Class* GetDirectInterface(uint32_t idx) {
+ Class* GetDirectInterface(uint32_t idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DCHECK(klass_ != NULL);
DCHECK(!klass_->IsPrimitive());
if (klass_->IsArrayClass()) {
@@ -174,7 +180,7 @@
}
}
- const char* GetSourceFile() {
+ const char* GetSourceFile() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
std::string descriptor(GetDescriptor());
const DexFile& dex_file = GetDexFile();
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
@@ -182,7 +188,7 @@
return dex_file.GetSourceFile(*dex_class_def);
}
- std::string GetLocation() {
+ std::string GetLocation() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DexCache* dex_cache = GetDexCache();
if (dex_cache != NULL && !klass_->IsProxyClass()) {
return dex_cache->GetLocation()->ToModifiedUtf8();
@@ -192,7 +198,7 @@
}
}
- const DexFile& GetDexFile() {
+ const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile* result = dex_file_;
if (result == NULL) {
const DexCache* dex_cache = GetDexCache();
@@ -202,7 +208,7 @@
return *result;
}
- DexCache* GetDexCache() {
+ DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DexCache* result = dex_cache_;
if (result == NULL) {
DCHECK(klass_ != NULL);
@@ -213,7 +219,8 @@
}
private:
- const DexFile::TypeList* GetInterfaceTypeList() {
+ const DexFile::TypeList* GetInterfaceTypeList()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile::TypeList* result = interface_type_list_;
if (result == NULL) {
const DexFile::ClassDef* class_def = GetClassDef();
@@ -263,7 +270,7 @@
}
field_ = new_f;
}
- const char* GetName() {
+ const char* GetName() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
if (!field_->GetDeclaringClass()->IsProxyClass()) {
const DexFile& dex_file = GetDexFile();
@@ -284,7 +291,7 @@
return Runtime::Current()->GetInternTable()->InternStrong(GetName());
}
}
- Class* GetType() {
+ Class* GetType() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
if (!field_->GetDeclaringClass()->IsProxyClass()) {
const DexFile& dex_file = GetDexFile();
@@ -299,7 +306,7 @@
return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
}
}
- const char* GetTypeDescriptor() {
+ const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
if (!field_->GetDeclaringClass()->IsProxyClass()) {
const DexFile& dex_file = GetDexFile();
@@ -312,27 +319,29 @@
return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
}
}
- Primitive::Type GetTypeAsPrimitiveType() {
+ Primitive::Type GetTypeAsPrimitiveType()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return Primitive::GetType(GetTypeDescriptor()[0]);
}
- bool IsPrimitiveType() {
+ bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
Primitive::Type type = GetTypeAsPrimitiveType();
return type != Primitive::kPrimNot;
}
- size_t FieldSize() {
+ size_t FieldSize() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
Primitive::Type type = GetTypeAsPrimitiveType();
return Primitive::FieldSize(type);
}
// The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
// If you need it longer, copy it into a std::string.
- const char* GetDeclaringClassDescriptor() {
+ const char* GetDeclaringClassDescriptor()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
uint16_t type_idx = field_->GetDeclaringClass()->GetDexTypeIndex();
if (type_idx != DexFile::kDexNoIndex16) {
const DexFile& dex_file = GetDexFile();
return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
} else {
- // Most likely a proxy class
+ // Most likely a proxy class.
ClassHelper kh(field_->GetDeclaringClass());
declaring_class_descriptor_ = kh.GetDescriptor();
return declaring_class_descriptor_.c_str();
@@ -340,7 +349,7 @@
}
private:
- DexCache* GetDexCache() {
+ DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DexCache* result = dex_cache_;
if (result == NULL) {
result = field_->GetDeclaringClass()->GetDexCache();
@@ -356,7 +365,7 @@
}
return result;
}
- const DexFile& GetDexFile() {
+ const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile* result = dex_file_;
if (result == NULL) {
const DexCache* dex_cache = GetDexCache();
@@ -378,22 +387,24 @@
class MethodHelper {
public:
MethodHelper()
- : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
- shorty_len_(0) {}
+ : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
+ shorty_len_(0) {}
explicit MethodHelper(const Method* m)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
: class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
shorty_len_(0) {
SetMethod(m);
}
MethodHelper(const Method* m, ClassLinker* l)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
: class_linker_(l), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
shorty_len_(0) {
SetMethod(m);
}
- void ChangeMethod(Method* new_m) {
+ void ChangeMethod(Method* new_m) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DCHECK(new_m != NULL);
if (dex_cache_ != NULL) {
Class* klass = new_m->GetDeclaringClass();
@@ -412,7 +423,7 @@
shorty_ = NULL;
}
- const char* GetName() {
+ const char* GetName() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
if (dex_method_idx != DexFile::kDexNoIndex16) {
@@ -433,14 +444,15 @@
}
}
- String* GetNameAsString() {
+ String* GetNameAsString() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
}
- const char* GetShorty() {
+ const char* GetShorty() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const char* result = shorty_;
if (result == NULL) {
const DexFile& dex_file = GetDexFile();
@@ -451,14 +463,14 @@
return result;
}
- uint32_t GetShortyLength() {
+ uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
if (shorty_ == NULL) {
GetShorty();
}
return shorty_len_;
}
- const std::string GetSignature() {
+ const std::string GetSignature() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
uint32_t dex_method_idx = method_->GetDexMethodIndex();
if (dex_method_idx != DexFile::kDexNoIndex16) {
@@ -468,17 +480,20 @@
}
}
- const DexFile::ProtoId& GetPrototype() {
+ const DexFile::ProtoId& GetPrototype()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
}
- const DexFile::TypeList* GetParameterTypeList() {
+ const DexFile::TypeList* GetParameterTypeList()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile::ProtoId& proto = GetPrototype();
return GetDexFile().GetProtoParameters(proto);
}
- ObjectArray<Class>* GetParameterTypes() {
+ ObjectArray<Class>* GetParameterTypes()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile::TypeList* params = GetParameterTypeList();
Class* array_class = GetClassLinker()->FindSystemClass("[Ljava/lang/Class;");
uint32_t num_params = params == NULL ? 0 : params->Size();
@@ -494,7 +509,7 @@
return result;
}
- Class* GetReturnType() {
+ Class* GetReturnType() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
@@ -502,7 +517,8 @@
return GetClassFromTypeIdx(return_type_idx);
}
- const char* GetReturnTypeDescriptor() {
+ const char* GetReturnTypeDescriptor()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
@@ -510,7 +526,8 @@
return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
}
- int32_t GetLineNumFromDexPC(uint32_t dex_pc) {
+ int32_t GetLineNumFromDexPC(uint32_t dex_pc)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
if (dex_pc == DexFile::kDexNoIndex) {
return method_->IsNative() ? -2 : -1;
} else {
@@ -519,7 +536,8 @@
}
}
- const char* GetDeclaringClassDescriptor() {
+ const char* GetDeclaringClassDescriptor()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
Class* klass = method_->GetDeclaringClass();
DCHECK(!klass->IsProxyClass());
uint16_t type_idx = klass->GetDexTypeIndex();
@@ -527,7 +545,8 @@
return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
}
- const char* GetDeclaringClassSourceFile() {
+ const char* GetDeclaringClassSourceFile()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const char* descriptor = GetDeclaringClassDescriptor();
const DexFile& dex_file = GetDexFile();
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
@@ -535,7 +554,8 @@
return dex_file.GetSourceFile(*dex_class_def);
}
- uint32_t GetClassDefIndex() {
+ uint32_t GetClassDefIndex()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const char* descriptor = GetDeclaringClassDescriptor();
const DexFile& dex_file = GetDexFile();
uint32_t index;
@@ -543,26 +563,29 @@
return index;
}
- ClassLoader* GetClassLoader() {
+ ClassLoader* GetClassLoader()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return method_->GetDeclaringClass()->GetClassLoader();
}
- bool IsStatic() {
+ bool IsStatic()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return method_->IsStatic();
}
- bool IsClassInitializer() {
+ bool IsClassInitializer() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return IsStatic() && StringPiece(GetName()) == "<clinit>";
}
- size_t NumArgs() {
+ size_t NumArgs() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
// "1 +" because the first in Args is the receiver.
// "- 1" because we don't count the return type.
return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
}
// Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods
- bool IsParamALongOrDouble(size_t param) {
+ bool IsParamALongOrDouble(size_t param)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK_LT(param, NumArgs());
if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
@@ -574,7 +597,7 @@
}
// Is the specified parameter a reference, where parameter 0 is 'this' for instance methods
- bool IsParamAReference(size_t param) {
+ bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK_LT(param, NumArgs());
if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
@@ -584,7 +607,8 @@
return GetShorty()[param] == 'L'; // An array also has a shorty character of 'L' (not '[')
}
- bool HasSameNameAndSignature(MethodHelper* other) {
+ bool HasSameNameAndSignature(MethodHelper* other)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
if (GetDexCache() == other->GetDexCache()) {
const DexFile& dex_file = GetDexFile();
const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
@@ -597,15 +621,18 @@
return name == other_name && GetSignature() == other->GetSignature();
}
- const DexFile::CodeItem* GetCodeItem() {
+ const DexFile::CodeItem* GetCodeItem()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
}
- bool IsResolvedTypeIdx(uint16_t type_idx) const {
+ bool IsResolvedTypeIdx(uint16_t type_idx) const
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
}
- Class* GetClassFromTypeIdx(uint16_t type_idx) {
+ Class* GetClassFromTypeIdx(uint16_t type_idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
if (type == NULL) {
type = GetClassLinker()->ResolveType(type_idx, method_);
@@ -614,16 +641,18 @@
return type;
}
- const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
+ const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
}
- Class* GetDexCacheResolvedType(uint16_t type_idx) {
+ Class* GetDexCacheResolvedType(uint16_t type_idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return GetDexCache()->GetResolvedType(type_idx);
}
- const DexFile& GetDexFile() {
+ const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
const DexFile* result = dex_file_;
if (result == NULL) {
const DexCache* dex_cache = GetDexCache();
@@ -633,7 +662,7 @@
return *result;
}
- DexCache* GetDexCache() {
+ DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
DexCache* result = dex_cache_;
if (result == NULL) {
Class* klass = method_->GetDeclaringClass();
@@ -646,7 +675,8 @@
private:
// Set the method_ field, for proxy methods looking up the interface method via the resolved
// methods table.
- void SetMethod(const Method* method) {
+ void SetMethod(const Method* method)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
if (method != NULL) {
Class* klass = method->GetDeclaringClass();
if (klass->IsProxyClass()) {