changeset 8328:6b6cbd8b8914

Support deoptimizing before the entry to a synchronized method.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 17 Mar 2013 21:20:39 +0100
parents e24fb475bdec
children 985e5188964f
files src/cpu/x86/vm/interpreterGenerator_x86.hpp src/cpu/x86/vm/templateInterpreter_x86_64.cpp src/share/vm/interpreter/templateInterpreter.cpp src/share/vm/interpreter/templateInterpreterGenerator.hpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/vframeArray.cpp src/share/vm/utilities/exceptions.hpp
diffstat 7 files changed, 37 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Sun Mar 17 21:20:39 2013 +0100
@@ -30,6 +30,8 @@
 //
   friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Sun Mar 17 21:20:39 2013 +0100
@@ -204,13 +204,26 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
+address InterpreterGenerator::generate_deopt_entry_for(TosState state,
                                                                int step) {
   address entry = __ pc();
   // NULL last_sp until next java call
   __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
   __ restore_bcp();
   __ restore_locals();
+  // Check if we need to take lock at entry of synchronized method.
+  {
+    Label L;
+    __ cmpb(Address(r15_thread, Thread::pending_monitorenter_offset()), 0);
+    __ jcc(Assembler::zero, L);
+    // Clear flag.
+    __ movb(Address(r15_thread, Thread::pending_monitorenter_offset()), 0);
+    // Satisfy calling convention for lock_method().
+    __ get_method(rbx);
+    // Take lock.
+    lock_method();
+    __ bind(L);
+  }
   // handle exceptions
   {
     Label L;
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Sun Mar 17 21:20:39 2013 +0100
@@ -180,7 +180,7 @@
 #endif // !PRODUCT
 EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];
 EntryPoint TemplateInterpreter::_earlyret_entry;
-EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];
+EntryPoint TemplateInterpreter::_deopt_entry[TemplateInterpreter::number_of_deopt_entries ];
 EntryPoint TemplateInterpreter::_continuation_entry;
 EntryPoint TemplateInterpreter::_safept_entry;
 
@@ -272,15 +272,15 @@
     for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) {
       Interpreter::_deopt_entry[i] =
         EntryPoint(
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(atos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(ltos, i),
-          generate_deopt_entry_for(ftos, i),
-          generate_deopt_entry_for(dtos, i),
-          generate_deopt_entry_for(vtos, i)
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(atos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ltos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ftos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(dtos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(vtos, i)
         );
     }
   }
--- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Sun Mar 17 21:20:39 2013 +0100
@@ -55,7 +55,6 @@
   address generate_continuation_for(TosState state);
   address generate_return_entry_for(TosState state, int step);
   address generate_earlyret_entry_for(TosState state);
-  address generate_deopt_entry_for(TosState state, int step);
   address generate_safept_entry_for(TosState state, address runtime_entry);
   void    generate_throw_exception();
 
--- a/src/share/vm/runtime/deoptimization.cpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Sun Mar 17 21:20:39 2013 +0100
@@ -1316,6 +1316,10 @@
 
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
+    if (trap_bci == SynchronizationEntryBCI) {
+      trap_bci = 0;
+      Thread::current()->set_pending_monitorenter(true);
+    }
     Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
     if (trap_scope->rethrow_exception()) {
--- a/src/share/vm/runtime/vframeArray.cpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/share/vm/runtime/vframeArray.cpp	Sun Mar 17 21:20:39 2013 +0100
@@ -286,7 +286,7 @@
 
   _frame.patch_pc(thread, pc);
 
-  assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
+  assert (!method()->is_synchronized() || locks > 0 || raw_bci() == SynchronizationEntryBCI, "synchronized methods must have monitors");
 
   BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
   for (int index = 0; index < locks; index++) {
--- a/src/share/vm/utilities/exceptions.hpp	Sun Mar 17 21:14:35 2013 +0100
+++ b/src/share/vm/utilities/exceptions.hpp	Sun Mar 17 21:20:39 2013 +0100
@@ -61,6 +61,7 @@
   friend class VMStructs;
 
  protected:
+  bool _pending_monitorenter;
   oop  _pending_exception;                       // Thread has gc actions.
   const char* _exception_file;                   // file information for exception (debugging only)
   int         _exception_line;                   // line information for exception (debugging only)
@@ -79,9 +80,13 @@
   bool has_pending_exception() const             { return _pending_exception != NULL; }
   const char* exception_file() const             { return _exception_file; }
   int  exception_line() const                    { return _exception_line; }
+  bool has_pending_monitorenter() const          { return _pending_monitorenter; }
 
   // Code generation support
   static ByteSize pending_exception_offset()     { return byte_offset_of(ThreadShadow, _pending_exception); }
+  static ByteSize pending_monitorenter_offset()  { return byte_offset_of(ThreadShadow, _pending_monitorenter); }
+
+  bool set_pending_monitorenter(bool b)          { return _pending_monitorenter = b; }
 
   // use THROW whenever possible!
   void set_pending_exception(oop exception, const char* file, int line);
@@ -90,7 +95,7 @@
   void clear_pending_exception();
 
   ThreadShadow() : _pending_exception(NULL),
-                   _exception_file(NULL), _exception_line(0) {}
+                   _exception_file(NULL), _exception_line(0), _pending_monitorenter(false) {}
 };