[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/arm/footer.S b/runtime/interpreter/mterp/arm/footer.S
index 617f572..1dba856 100644
--- a/runtime/interpreter/mterp/arm/footer.S
+++ b/runtime/interpreter/mterp/arm/footer.S
@@ -150,12 +150,8 @@
b MterpDone
MterpReturn:
ldr r2, [rFP, #OFF_FP_RESULT_REGISTER]
- ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
str r0, [r2]
str r1, [r2, #4]
- mov r0, rSELF
- ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
- blne MterpSuspendCheck @ (self)
mov r0, #1 @ signal return to caller.
MterpDone:
add sp, sp, #4 @ un-align 64
diff --git a/runtime/interpreter/mterp/arm/op_check_cast.S b/runtime/interpreter/mterp/arm/op_check_cast.S
index 3e3ac70..24eba45 100644
--- a/runtime/interpreter/mterp/arm/op_check_cast.S
+++ b/runtime/interpreter/mterp/arm/op_check_cast.S
@@ -5,10 +5,10 @@
EXPORT_PC
FETCH r0, 1 @ r0<- BBBB
mov r1, rINST, lsr #8 @ r1<- AA
- GET_VREG r1, r1 @ r1<- object
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
- bl MterpCheckCast @ (index, obj, method, self)
+ bl MterpCheckCast @ (index, &obj, method, self)
PREFETCH_INST 2
cmp r0, #0
bne MterpPossibleException
diff --git a/runtime/interpreter/mterp/arm/op_instance_of.S b/runtime/interpreter/mterp/arm/op_instance_of.S
index e94108c..d76f0b0 100644
--- a/runtime/interpreter/mterp/arm/op_instance_of.S
+++ b/runtime/interpreter/mterp/arm/op_instance_of.S
@@ -8,12 +8,12 @@
EXPORT_PC
FETCH r0, 1 @ r0<- CCCC
mov r1, rINST, lsr #12 @ r1<- B
- GET_VREG r1, r1 @ r1<- vB (object)
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
mov r9, rINST, lsr #8 @ r9<- A+
and r9, r9, #15 @ r9<- A
- bl MterpInstanceOf @ (index, obj, method, self)
+ bl MterpInstanceOf @ (index, &obj, method, self)
ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
PREFETCH_INST 2
cmp r1, #0 @ exception pending?
diff --git a/runtime/interpreter/mterp/arm/op_return.S b/runtime/interpreter/mterp/arm/op_return.S
index a4ffd04..1888373 100644
--- a/runtime/interpreter/mterp/arm/op_return.S
+++ b/runtime/interpreter/mterp/arm/op_return.S
@@ -6,6 +6,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
diff --git a/runtime/interpreter/mterp/arm/op_return_void.S b/runtime/interpreter/mterp/arm/op_return_void.S
index f6dfd99..cbea2bf 100644
--- a/runtime/interpreter/mterp/arm/op_return_void.S
+++ b/runtime/interpreter/mterp/arm/op_return_void.S
@@ -1,5 +1,9 @@
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
diff --git a/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S b/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
index 7322940..2dde7ae 100644
--- a/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
+++ b/runtime/interpreter/mterp/arm/op_return_void_no_barrier.S
@@ -1,3 +1,7 @@
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
diff --git a/runtime/interpreter/mterp/arm/op_return_wide.S b/runtime/interpreter/mterp/arm/op_return_wide.S
index 2881c87..cfab530 100644
--- a/runtime/interpreter/mterp/arm/op_return_wide.S
+++ b/runtime/interpreter/mterp/arm/op_return_wide.S
@@ -4,6 +4,10 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
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>));
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 9ae98a2..78c784b 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -599,6 +599,10 @@
/* File: arm/op_return_void.S */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
@@ -615,6 +619,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
@@ -630,6 +638,10 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
add r2, rFP, r2, lsl #2 @ r2<- &fp[AA]
ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1
@@ -648,6 +660,10 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
bl MterpThreadFenceForConstructor
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r2, rINST, lsr #8 @ r2<- AA
GET_VREG r0, r2 @ r0<- vAA
mov r1, #0
@@ -878,10 +894,10 @@
EXPORT_PC
FETCH r0, 1 @ r0<- BBBB
mov r1, rINST, lsr #8 @ r1<- AA
- GET_VREG r1, r1 @ r1<- object
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
- bl MterpCheckCast @ (index, obj, method, self)
+ bl MterpCheckCast @ (index, &obj, method, self)
PREFETCH_INST 2
cmp r0, #0
bne MterpPossibleException
@@ -903,12 +919,12 @@
EXPORT_PC
FETCH r0, 1 @ r0<- CCCC
mov r1, rINST, lsr #12 @ r1<- B
- GET_VREG r1, r1 @ r1<- vB (object)
+ VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object
ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method
mov r3, rSELF @ r3<- self
mov r9, rINST, lsr #8 @ r9<- A+
and r9, r9, #15 @ r9<- A
- bl MterpInstanceOf @ (index, obj, method, self)
+ bl MterpInstanceOf @ (index, &obj, method, self)
ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET]
PREFETCH_INST 2
cmp r1, #0 @ exception pending?
@@ -3385,6 +3401,10 @@
.balign 128
.L_op_return_void_no_barrier: /* 0x73 */
/* File: arm/op_return_void_no_barrier.S */
+ ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
+ mov r0, rSELF
+ ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ blne MterpSuspendCheck @ (self)
mov r0, #0
mov r1, #0
b MterpReturn
@@ -12183,12 +12203,8 @@
b MterpDone
MterpReturn:
ldr r2, [rFP, #OFF_FP_RESULT_REGISTER]
- ldr lr, [rSELF, #THREAD_FLAGS_OFFSET]
str r0, [r2]
str r1, [r2, #4]
- mov r0, rSELF
- ands lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
- blne MterpSuspendCheck @ (self)
mov r0, #1 @ signal return to caller.
MterpDone:
add sp, sp, #4 @ un-align 64
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 923d502..e2918dc 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -575,6 +575,12 @@
/* File: x86/op_return_void.S */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
@@ -591,6 +597,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
@@ -605,6 +617,12 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- v[AA+0]
GET_VREG_HIGH %ecx rINST # ecx <- v[AA+1]
jmp MterpReturn
@@ -622,6 +640,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
@@ -827,13 +851,13 @@
EXPORT_PC
movzwl 2(rPC), %eax # eax <- BBBB
movl %eax, OUT_ARG0(%esp)
- GET_VREG %ecx rINST
+ leal VREG_ADDRESS(rINST), %ecx
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpCheckCast # (index, obj, method, self)
+ call MterpCheckCast # (index, &obj, method, self)
REFRESH_IBASE
testl %eax, %eax
jnz MterpPossibleException
@@ -855,13 +879,13 @@
movl %eax, OUT_ARG0(%esp)
movl rINST, %eax # eax <- BA
sarl $4, %eax # eax <- B
- GET_VREG %ecx %eax # Get object
+ leal VREG_ADDRESS(%eax), %ecx # Get object address
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpInstanceOf # (index, obj, method, self)
+ call MterpInstanceOf # (index, &obj, method, self)
movl rSELF, %ecx
REFRESH_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -3145,6 +3169,12 @@
.balign 128
.L_op_return_void_no_barrier: /* 0x73 */
/* File: x86/op_return_void_no_barrier.S */
+ movl rSELF, %eax
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
@@ -12921,12 +12951,6 @@
movl OFF_FP_RESULT_REGISTER(rFP), %edx
movl %eax, (%edx)
movl %ecx, 4(%edx)
- movl rSELF, %eax
- testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
- jz 1f
- movl %eax, OUT_ARG0(%esp)
- call MterpSuspendCheck
-1:
mov $1, %eax
MterpDone:
/* Restore callee save register */
diff --git a/runtime/interpreter/mterp/x86/footer.S b/runtime/interpreter/mterp/x86/footer.S
index 8f79b37..a2a36c4 100644
--- a/runtime/interpreter/mterp/x86/footer.S
+++ b/runtime/interpreter/mterp/x86/footer.S
@@ -169,12 +169,6 @@
movl OFF_FP_RESULT_REGISTER(rFP), %edx
movl %eax, (%edx)
movl %ecx, 4(%edx)
- movl rSELF, %eax
- testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
- jz 1f
- movl %eax, OUT_ARG0(%esp)
- call MterpSuspendCheck
-1:
mov $$1, %eax
MterpDone:
/* Restore callee save register */
diff --git a/runtime/interpreter/mterp/x86/op_check_cast.S b/runtime/interpreter/mterp/x86/op_check_cast.S
index 3d85f5e..018432a 100644
--- a/runtime/interpreter/mterp/x86/op_check_cast.S
+++ b/runtime/interpreter/mterp/x86/op_check_cast.S
@@ -5,13 +5,13 @@
EXPORT_PC
movzwl 2(rPC), %eax # eax <- BBBB
movl %eax, OUT_ARG0(%esp)
- GET_VREG %ecx rINST
+ leal VREG_ADDRESS(rINST), %ecx
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpCheckCast # (index, obj, method, self)
+ call MterpCheckCast # (index, &obj, method, self)
REFRESH_IBASE
testl %eax, %eax
jnz MterpPossibleException
diff --git a/runtime/interpreter/mterp/x86/op_instance_of.S b/runtime/interpreter/mterp/x86/op_instance_of.S
index cfbd4a0..c9bfba5 100644
--- a/runtime/interpreter/mterp/x86/op_instance_of.S
+++ b/runtime/interpreter/mterp/x86/op_instance_of.S
@@ -10,13 +10,13 @@
movl %eax, OUT_ARG0(%esp)
movl rINST, %eax # eax <- BA
sarl $$4, %eax # eax <- B
- GET_VREG %ecx %eax # Get object
+ leal VREG_ADDRESS(%eax), %ecx # Get object address
movl %ecx, OUT_ARG1(%esp)
movl OFF_FP_METHOD(rFP),%eax
movl %eax, OUT_ARG2(%esp)
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp)
- call MterpInstanceOf # (index, obj, method, self)
+ call MterpInstanceOf # (index, &obj, method, self)
movl rSELF, %ecx
REFRESH_IBASE_FROM_SELF %ecx
cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx)
diff --git a/runtime/interpreter/mterp/x86/op_return.S b/runtime/interpreter/mterp/x86/op_return.S
index 1658322..183b3bf 100644
--- a/runtime/interpreter/mterp/x86/op_return.S
+++ b/runtime/interpreter/mterp/x86/op_return.S
@@ -6,6 +6,12 @@
/* op vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- vAA
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_void.S b/runtime/interpreter/mterp/x86/op_return_void.S
index b74446e..f3e24c7 100644
--- a/runtime/interpreter/mterp/x86/op_return_void.S
+++ b/runtime/interpreter/mterp/x86/op_return_void.S
@@ -1,5 +1,11 @@
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S b/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
index abc7c4d..add4e20 100644
--- a/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
+++ b/runtime/interpreter/mterp/x86/op_return_void_no_barrier.S
@@ -1,3 +1,9 @@
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
xorl %eax, %eax
xorl %ecx, %ecx
jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86/op_return_wide.S b/runtime/interpreter/mterp/x86/op_return_wide.S
index 00effd6..34a3380 100644
--- a/runtime/interpreter/mterp/x86/op_return_wide.S
+++ b/runtime/interpreter/mterp/x86/op_return_wide.S
@@ -4,6 +4,12 @@
/* return-wide vAA */
.extern MterpThreadFenceForConstructor
call MterpThreadFenceForConstructor
+ movl rSELF, %eax
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
+ jz 1f
+ movl %eax, OUT_ARG0(%esp)
+ call MterpSuspendCheck
+1:
GET_VREG %eax rINST # eax <- v[AA+0]
GET_VREG_HIGH %ecx rINST # ecx <- v[AA+1]
jmp MterpReturn