[WIP] ART Mterp: fix for hidden gc roots
To support moving gc, we must not hold onto any references solely
in registers across potential gc points. This was happening during
returns, instance-of and check-cast.
[testing in progress]
Change-Id: I367750658c5716960737f0666e46800240fd392d
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 9975458..0afd276 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -274,13 +274,15 @@
return false;
}
-extern "C" bool MterpCheckCast(uint32_t index, Object* obj, art::ArtMethod* method,
- Thread* self)
+extern "C" bool MterpCheckCast(uint32_t index, StackReference<mirror::Object>* vreg_addr,
+ art::ArtMethod* method, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
if (UNLIKELY(c == nullptr)) {
return true;
}
+ // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
+ Object* obj = vreg_addr->AsMirrorPtr();
if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
ThrowClassCastException(c, obj->GetClass());
return true;
@@ -288,13 +290,15 @@
return false;
}
-extern "C" bool MterpInstanceOf(uint32_t index, Object* obj, art::ArtMethod* method,
- Thread* self)
+extern "C" bool MterpInstanceOf(uint32_t index, StackReference<mirror::Object>* vreg_addr,
+ art::ArtMethod* method, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
if (UNLIKELY(c == nullptr)) {
return false; // Caller will check for pending exception. Return value unimportant.
}
+ // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
+ Object* obj = vreg_addr->AsMirrorPtr();
return (obj != nullptr) && obj->InstanceOf(c);
}
@@ -505,8 +509,7 @@
uint64_t* new_value, Thread* self)
SHARED_REQUIRES(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
- ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
- sizeof(int64_t));
+ ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
if (LIKELY(field != nullptr)) {
// Compiled code can't use transactional mode.
field->Set64<false>(field->GetDeclaringClass(), *new_value);
@@ -524,8 +527,7 @@
extern "C" int artSet8InstanceFromMterp(uint32_t field_idx, mirror::Object* obj, uint8_t new_value,
ArtMethod* referrer)
SHARED_REQUIRES(Locks::mutator_lock_) {
- ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
- sizeof(int8_t));
+ ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
if (LIKELY(field != nullptr && obj != nullptr)) {
Primitive::Type type = field->GetTypeAsPrimitiveType();
if (type == Primitive::kPrimBoolean) {
@@ -582,7 +584,7 @@
}
extern "C" int artSetObjInstanceFromMterp(uint32_t field_idx, mirror::Object* obj,
- mirror::Object* new_value, ArtMethod* referrer)
+ mirror::Object* new_value, ArtMethod* referrer)
SHARED_REQUIRES(Locks::mutator_lock_) {
ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
sizeof(mirror::HeapReference<mirror::Object>));