United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6307266 JIT compilation in mixed mode may break synchronization
6307266 : JIT compilation in mixed mode may break synchronization

Details
Type:
Bug
Submit Date:
2005-08-05
Status:
Closed
Updated Date:
2010-04-03
Project Name:
JDK
Resolved Date:
2005-08-26
Component:
hotspot
OS:
solaris,generic
Sub-Component:
compiler
CPU:
sparc,generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
5.0u3,6
Fixed Versions:
6

Related Reports
Backport:
Backport:
Backport:
Backport:

Sub Tasks

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
                                     
2005-08-11
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.
                                     
2005-08-08



Hardware and Software, Engineered to Work Together