Numerous fixes to compiler and verifier for cts vm-tests.
ClassNotFoundExceptions in ResolveType are converted to
NoClassDefFoundErrors.
Compiler checks for puts into final fields.
Method resolution searches direct methods if an appropriate virtual
method can't be found.
Invocations of <clinit> are rejected by the verifier.
Invoke-super and invoke-virtual can't be used on private methods.
Using invoke-interface on non-interface methods and not using
invoke-interface on interface methods leads do an error.
Change-Id: Ia589f1ffccf91b62812ee34c8c5fae1aaf3798c6
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 38d2699..8dd7eed 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -76,6 +76,13 @@
PrettyDescriptor(referrer).c_str());
}
+static void ThrowNewIllegalAccessErrorFinalField(Thread* self, const Method* referrer, Field* accessed) {
+ self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+ "Final field '%s' cannot be written to by method '%s'",
+ PrettyField(accessed, false).c_str(),
+ PrettyMethod(referrer).c_str());
+}
+
static void ThrowNewIllegalAccessErrorMethod(Thread* self, Class* referrer, Method* accessed) {
self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Method '%s' is inaccessible to class '%s'",
@@ -580,7 +587,7 @@
// Fast path field resolution that can't throw exceptions
static Field* FindFieldFast(uint32_t field_idx, const Method* referrer, bool is_primitive,
- size_t expected_size) {
+ size_t expected_size, bool is_set) {
Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
if (UNLIKELY(resolved_field == NULL)) {
return NULL;
@@ -593,7 +600,8 @@
Class* referring_class = referrer->GetDeclaringClass();
if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
!referring_class->CanAccessMember(fields_class,
- resolved_field->GetAccessFlags()))) {
+ resolved_field->GetAccessFlags()) ||
+ (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
// illegal access
return NULL;
}
@@ -608,7 +616,7 @@
// Slow path field resolution and declaring class initialization
Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
- bool is_static, bool is_primitive, size_t expected_size) {
+ bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
if (UNLIKELY(resolved_field == NULL)) {
@@ -624,6 +632,9 @@
resolved_field->GetAccessFlags()))) {
ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
return NULL; // failure
+ } else if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
+ ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
+ return NULL; // failure
} else {
FieldHelper fh(resolved_field);
if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
@@ -655,12 +666,12 @@
extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int32_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
if (LIKELY(field != NULL)) {
return field->Get32(NULL);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, true, sizeof(int32_t));
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int32_t));
if (LIKELY(field != NULL)) {
return field->Get32(NULL);
}
@@ -669,12 +680,12 @@
extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int64_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
if (LIKELY(field != NULL)) {
return field->Get64(NULL);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, true, sizeof(int64_t));
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int64_t));
if (LIKELY(field != NULL)) {
return field->Get64(NULL);
}
@@ -683,12 +694,12 @@
extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, false, sizeof(Object*));
+ Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
if (LIKELY(field != NULL)) {
return field->GetObj(NULL);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, false, sizeof(Object*));
+ field = FindFieldFromCode(field_idx, referrer, self, true, false, false, sizeof(Object*));
if (LIKELY(field != NULL)) {
return field->GetObj(NULL);
}
@@ -697,12 +708,12 @@
extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int32_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
if (LIKELY(field != NULL && obj != NULL)) {
return field->Get32(obj);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, false, true, sizeof(int32_t));
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int32_t));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, true);
@@ -715,12 +726,12 @@
extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int64_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
if (LIKELY(field != NULL && obj != NULL)) {
return field->Get64(obj);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, false, true, sizeof(int64_t));
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int64_t));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, true);
@@ -733,12 +744,12 @@
extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, false, sizeof(Object*));
+ Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
if (LIKELY(field != NULL && obj != NULL)) {
return field->GetObj(obj);
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, false, false, sizeof(Object*));
+ field = FindFieldFromCode(field_idx, referrer, self, false, false, false, sizeof(Object*));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, true);
@@ -751,13 +762,13 @@
extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int32_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
if (LIKELY(field != NULL)) {
field->Set32(NULL, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, true, sizeof(int32_t));
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int32_t));
if (LIKELY(field != NULL)) {
field->Set32(NULL, new_value);
return 0; // success
@@ -767,13 +778,13 @@
extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
uint64_t new_value, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int64_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
if (LIKELY(field != NULL)) {
field->Set64(NULL, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, true, sizeof(int64_t));
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int64_t));
if (LIKELY(field != NULL)) {
field->Set64(NULL, new_value);
return 0; // success
@@ -783,7 +794,7 @@
extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, false, sizeof(Object*));
+ Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
if (LIKELY(field != NULL)) {
if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
field->SetObj(NULL, new_value);
@@ -791,7 +802,7 @@
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, true, false, sizeof(Object*));
+ field = FindFieldFromCode(field_idx, referrer, self, true, false, true, sizeof(Object*));
if (LIKELY(field != NULL)) {
field->SetObj(NULL, new_value);
return 0; // success
@@ -801,13 +812,13 @@
extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int32_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
if (LIKELY(field != NULL && obj != NULL)) {
field->Set32(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, false, true, sizeof(int32_t));
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int32_t));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, false);
@@ -823,14 +834,14 @@
Thread* self, Method** sp) {
Method* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
Method* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(Method*)];
- Field* field = FindFieldFast(field_idx, referrer, true, sizeof(int64_t));
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
if (LIKELY(field != NULL && obj != NULL)) {
field->Set64(obj, new_value);
return 0; // success
}
*sp = callee_save;
self->SetTopOfStack(sp, 0);
- field = FindFieldFromCode(field_idx, referrer, self, false, true, sizeof(int64_t));
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int64_t));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, false);
@@ -844,13 +855,13 @@
extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value,
const Method* referrer, Thread* self, Method** sp) {
- Field* field = FindFieldFast(field_idx, referrer, false, sizeof(Object*));
+ Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
if (LIKELY(field != NULL && obj != NULL)) {
field->SetObj(obj, new_value);
return 0; // success
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
- field = FindFieldFromCode(field_idx, referrer, self, false, false, sizeof(Object*));
+ field = FindFieldFromCode(field_idx, referrer, self, false, false, true, sizeof(Object*));
if (LIKELY(field != NULL)) {
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(self, field, false);