No access check support.
This CL adds support to disable access check when a method is preverified (at
compilation time) and we know we don't need to do any access check.
The interpreter has now two modes of execution: with or without access check.
This is realized by using a template function.
A new runtime access flag kAccPreverified is added onto each method belonging
to a preverified class. If this flag is set, we enter the interpreter in "no
access check" mode. Otherwise, we enter the interpreter in "with access check"
mode.
Change-Id: Ic34163421d5b0aca3d1bce22ef7c095dcf465a18
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 9242c87..f6225ed 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -142,7 +142,8 @@
}
mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer,
- Thread* self, FindFieldType type, size_t expected_size) {
+ Thread* self, FindFieldType type, size_t expected_size,
+ bool access_check) {
bool is_primitive;
bool is_set;
bool is_static;
@@ -162,12 +163,13 @@
if (UNLIKELY(resolved_field == NULL)) {
DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
return NULL; // Failure.
- } else {
+ }
+ mirror::Class* fields_class = resolved_field->GetDeclaringClass();
+ if (access_check) {
if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
return NULL;
}
- mirror::Class* fields_class = resolved_field->GetDeclaringClass();
mirror::Class* referring_class = referrer->GetDeclaringClass();
if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
!referring_class->CanAccessMember(fields_class,
@@ -203,23 +205,24 @@
is_primitive ? "primitive" : "non-primitive",
PrettyField(resolved_field, true).c_str());
return NULL; // failure
- } else if (!is_static) {
- // instance fields must be being accessed on an initialized class
- return resolved_field;
- } else {
- // If the class is initialized we're done.
- if (fields_class->IsInitialized()) {
- return resolved_field;
- } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
- // Otherwise let's ensure the class is initialized before resolving the field.
- return resolved_field;
- } else {
- DCHECK(self->IsExceptionPending()); // Throw exception and unwind
- return NULL; // failure
- }
}
}
}
+ if (!is_static) {
+ // instance fields must be being accessed on an initialized class
+ return resolved_field;
+ } else {
+ // If the class is initialized we're done.
+ if (fields_class->IsInitialized()) {
+ return resolved_field;
+ } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
+ // Otherwise let's ensure the class is initialized before resolving the field.
+ return resolved_field;
+ } else {
+ DCHECK(self->IsExceptionPending()); // Throw exception and unwind
+ return NULL; // failure
+ }
+ }
}
// Slow path method resolution