JDK-6307266 : JIT compilation in mixed mode may break synchronization
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 5.0u3,6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,solaris
  • CPU: generic,sparc
  • Submitted: 2005-08-05
  • Updated: 2010-04-03
  • Resolved: 2005-08-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other Other JDK 6
1.4.2_17-revFixed 1.4.2_18Fixed 5.0u17Fixed 6 b49Fixed
Description
Attached test works ok until internal loop is interpreted.
However, after it is executed number of times normally and
compiled by JIT it fails with 'java.lang.IllegalMonitorStateException' exception.

This problem is reproducible with both 1.5 and recent mustang builds.
It is not reproducible on Solaris x86 and linux x86.

Comments
SUGGESTED FIX The fix is to mirror the code on intel. *** 1,7 **** #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)c1_LIRAssembler_sparc.cpp 1.181 05/07/21 12:50:29 JVM" #endif /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ --- 1,7 ---- #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)c1_LIRAssembler_sparc.cpp 1.182 05/08/10 22:02:08 JVM" #endif /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ *** 222,256 **** } } } // Initialize monitors in the compiled activation. // Note: interpreter uses BasicObjectLock for monitors while compiler1 uses BasicLock ! { ! assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); ! int rounded_vm_local_words = ::round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); int monitor_offset = (locals_offset + BytesPerWord) + (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); for (int i = 0; i < number_of_locks; i++) { ! Address compiled_monitor_lock_address = frame_map()->address_for_monitor_lock_index(number_of_locks - i - 1); ! Address compiled_monitor_object_address = frame_map()->address_for_monitor_object_index(number_of_locks - i - 1); ! Address interpreter_monitor_address = Address(OSR_buf, 0, monitor_offset - (i * BasicObjectLock::size() * BytesPerWord)); #ifdef ASSERT // verify the interpreter's monitor has a non-null object { Label L; ! load(interpreter_monitor_address, O7, T_OBJECT, NULL, BasicObjectLock::obj_offset_in_bytes()); __ cmp(G0, O7); __ br(Assembler::notEqual, false, Assembler::pt, L); __ delayed()->nop(); __ stop("locked object is NULL"); __ bind(L); } #endif // ASSERT // Copy the lock field into the compiled activation. ! load(interpreter_monitor_address, O7, T_ADDRESS, NULL, BasicObjectLock::lock_offset_in_bytes()); ! store(O7, compiled_monitor_lock_address, T_ADDRESS, NULL); ! load(interpreter_monitor_address, O7, T_OBJECT, NULL, BasicObjectLock::obj_offset_in_bytes()); ! store(O7, compiled_monitor_object_address, T_OBJECT, NULL); } } // Pass the OSR buffer across the save if needed --- 222,252 ---- } } } // Initialize monitors in the compiled activation. // Note: interpreter uses BasicObjectLock for monitors while compiler1 uses BasicLock ! { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); int monitor_offset = (locals_offset + BytesPerWord) + (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); for (int i = 0; i < number_of_locks; i++) { ! int slot_offset = monitor_offset - ((i * BasicObjectLock::size()) * BytesPerWord); #ifdef ASSERT // verify the interpreter's monitor has a non-null object { Label L; ! load(Address(OSR_buf, 0, slot_offset + BasicObjectLock::obj_offset_in_bytes()), O7, T_OBJECT, NULL); __ cmp(G0, O7); __ br(Assembler::notEqual, false, Assembler::pt, L); __ delayed()->nop(); __ stop("locked object is NULL"); __ bind(L); } #endif // ASSERT // Copy the lock field into the compiled activation. ! load(Address(OSR_buf, 0, slot_offset + BasicObjectLock::lock_offset_in_bytes()), O7, T_ADDRESS, NULL); ! store(O7, frame_map()->address_for_monitor_lock_index(i), T_ADDRESS, NULL); ! load(Address(OSR_buf, 0, slot_offset + BasicObjectLock::obj_offset_in_bytes()), O7, T_ADDRESS, NULL); ! store(O7, frame_map()->address_for_monitor_object_index(i), T_OBJECT, NULL); } } // Pass the OSR buffer across the save if needed
11-08-2005

EVALUATION This is a bug in the order in which monitors are copied from the interpreter frame to the compiled frame. Strictly speaking this was broken in original sparc port of client but only in 1.4.1 did it become visible because we switched to using BasicObjectLocks so we stopped examining unlocked object, relying instead of the BasicObjectLock pointing to the correct object. The fix is simply to reverse order of transfering locks from the interpeter frame.
08-08-2005