Fix JNI compiler for synchronized methods.
Calls to the monitor enter/exit routines were passing the JNI env with
the iterator in the wrong position. Reset the iterator to make sure it
is in the correct position for the monitor enter/exit call.
Also fix clobbering of arguments in registers when calling monitor enter
for synchronized methods on ARM.
Also some tidying of code/comments.
Change-Id: I5bf1dd7e65d925e768411cb5865919ee5f54edbf
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index bdf2e45..0300ad1 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -73,6 +73,34 @@
// JNI calling convention
+size_t JniCallingConvention::FrameSize() {
+ // Method* and spill area size
+ size_t frame_data_size = kPointerSize + SpillAreaSize();
+ // Handles plus 2 words for SHB header
+ size_t handle_area_size = (HandleCount() + 2) * kPointerSize;
+ // Plus return value spill area size
+ return RoundUp(frame_data_size + handle_area_size + SizeOfReturnValue(), 16);
+}
+
+size_t JniCallingConvention::SpillAreaSize() {
+ // Space for link register. For synchronized methods we need enough space to
+ // save R1, R2 and R3 (R0 is the method register and always preserved)
+ return GetMethod()->IsSynchronized() ? (4 * kPointerSize) : kPointerSize;
+}
+
+std::vector<ManagedRegister>* JniCallingConvention::ComputeRegsToSpillPreCall()
+{
+ // A synchronized method will call monitor enter clobbering R1, R2 and R3
+ // unless they are spilled.
+ std::vector<ManagedRegister>* result = new std::vector<ManagedRegister>();
+ if (GetMethod()->IsSynchronized()) {
+ result->push_back(ManagedRegister::FromCoreRegister(R1));
+ result->push_back(ManagedRegister::FromCoreRegister(R2));
+ result->push_back(ManagedRegister::FromCoreRegister(R3));
+ }
+ return result;
+}
+
// Will reg be crushed by an outgoing argument?
bool JniCallingConvention::IsOutArgRegister(ManagedRegister) {
// R0 holds the method register and will be crushed by the JNIEnv*