Runtime access checks on virtual method calls
At verification time we may not know that an illegal access or method
not found exception should be raised and so we defer the decision to
runtime. When the decision is deferred we perform an appropriate slow
path method invocation that can check for access violations.
This change also attempts to reduce code duplication, improve the
diagnostic information in exceptions, clean up field slow paths slightly
and to move the slow path calls lower in the Thread class so that they
don't effect the offsets of data items when calls are added or removed.
Change-Id: I8376b83dcd7e302cbbddf44c1a55a25687b9dcdb
diff --git a/src/object.h b/src/object.h
index 19ca325..738d2b0 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1015,7 +1015,7 @@
template<class T>
T* ObjectArray<T>::Get(int32_t i) const {
- if (!IsValidIndex(i)) {
+ if (UNLIKELY(!IsValidIndex(i))) {
return NULL;
}
MemberOffset data_offset(DataOffset().Int32Value() + i * sizeof(Object*));
@@ -1523,7 +1523,7 @@
// Given a method implemented by this class, but potentially from a
// super class or interface, return the specific implementation
// method for this class.
- Method* FindVirtualMethodForInterface(Method* method, bool can_throw);
+ Method* FindVirtualMethodForInterface(Method* method);
Method* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const;
@@ -1532,7 +1532,7 @@
return method;
}
if (method->GetDeclaringClass()->IsInterface()) {
- return FindVirtualMethodForInterface(method, true);
+ return FindVirtualMethodForInterface(method);
}
return FindVirtualMethodForVirtual(method);
}
@@ -1941,10 +1941,10 @@
template<class T>
void ObjectArray<T>::Set(int32_t i, T* object) {
- if (IsValidIndex(i)) {
+ if (LIKELY(IsValidIndex(i))) {
if (object != NULL) {
Class* element_class = GetClass()->GetComponentType();
- if (!object->InstanceOf(element_class)) {
+ if (UNLIKELY(!object->InstanceOf(element_class))) {
ThrowArrayStoreException(object);
return;
}
@@ -2261,6 +2261,9 @@
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_),
new_detail_message, false);
}
+ String* GetDetailMessage() const {
+ return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
+ }
std::string Dump() const;
// This is a runtime version of initCause, you shouldn't use it if initCause may have been