< prev index next >

src/hotspot/share/runtime/frame.cpp

Print this page
@@ -36,10 +36,11 @@
  #include "memory/universe.hpp"
  #include "oops/markWord.hpp"
  #include "oops/method.hpp"
  #include "oops/methodData.hpp"
  #include "oops/oop.inline.hpp"
+ #include "oops/inlineKlass.hpp"
  #include "oops/verifyOopClosure.hpp"
  #include "prims/methodHandles.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/javaCalls.hpp"

@@ -51,10 +52,13 @@
  #include "runtime/stubRoutines.hpp"
  #include "runtime/thread.inline.hpp"
  #include "utilities/debug.hpp"
  #include "utilities/decoder.hpp"
  #include "utilities/formatBuffer.hpp"
+ #ifdef COMPILER1
+ #include "c1/c1_Runtime1.hpp"
+ #endif
  
  RegisterMap::RegisterMap(JavaThread *thread, bool update_map, bool process_frames) {
    _thread         = thread;
    _update_map     = update_map;
    _process_frames = process_frames;

@@ -285,10 +289,29 @@
                          cm->deopt_mh_handler_begin() :
                          cm->deopt_handler_begin();
  
    // Save the original pc before we patch in the new one
    cm->set_original_pc(this, pc());
+ 
+ #ifdef COMPILER1
+   if (cm->is_compiled_by_c1() && cm->method()->has_scalarized_args() &&
+       pc() < cm->verified_inline_entry_point()) {
+     // The VEP and VIEP(RO) of C1-compiled methods call into the runtime to buffer scalarized value
+     // type args. We can't deoptimize at that point because the buffers have not yet been initialized.
+     // Also, if the method is synchronized, we first need to acquire the lock.
+     // Don't patch the return pc to delay deoptimization until we enter the method body (the check
+     // addedin LIRGenerator::do_Base will detect the pending deoptimization by checking the original_pc).
+ #if defined ASSERT && !defined AARCH64   // Stub call site does not look like NativeCall on AArch64
+     NativeCall* call = nativeCall_before(this->pc());
+     address dest = call->destination();
+     assert(dest == Runtime1::entry_for(Runtime1::buffer_inline_args_no_receiver_id) ||
+            dest == Runtime1::entry_for(Runtime1::buffer_inline_args_id), "unexpected safepoint in entry point");
+ #endif
+     return;
+   }
+ #endif
+ 
    patch_pc(thread, deopt);
  
  #ifdef ASSERT
    {
      RegisterMap map(thread, false);

@@ -679,11 +702,11 @@
    int          _max_locals;
    int          _max_stack;
  
   public:
    InterpreterFrameClosure(const frame* fr, int max_locals, int max_stack,
-                           OopClosure* f) {
+                           OopClosure* f, BufferedValueClosure* bvt_f) {
      _fr         = fr;
      _max_locals = max_locals;
      _max_stack  = max_stack;
      _f          = f;
    }

@@ -691,11 +714,13 @@
    void offset_do(int offset) {
      oop* addr;
      if (offset < _max_locals) {
        addr = (oop*) _fr->interpreter_frame_local_at(offset);
        assert((intptr_t*)addr >= _fr->sp(), "must be inside the frame");
-       _f->do_oop(addr);
+       if (_f != NULL) {
+         _f->do_oop(addr);
+       }
      } else {
        addr = (oop*) _fr->interpreter_frame_expression_stack_at((offset - _max_locals));
        // In case of exceptions, the expression stack is invalid and the esp will be reset to express
        // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).
        bool in_stack;

@@ -703,11 +728,13 @@
          in_stack = (intptr_t*)addr <= _fr->interpreter_frame_tos_address();
        } else {
          in_stack = (intptr_t*)addr >= _fr->interpreter_frame_tos_address();
        }
        if (in_stack) {
-         _f->do_oop(addr);
+         if (_f != NULL) {
+           _f->do_oop(addr);
+         }
        }
      }
    }
  
    int max_locals()  { return _max_locals; }

@@ -878,11 +905,11 @@
          oops_interpreted_arguments_do(signature, has_receiver, f);
        }
      }
    }
  
-   InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f);
+   InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f, NULL);
  
    // process locals & expression stack
    InterpreterOopMap mask;
    if (query_oop_map_cache) {
      m->mask_for(bci, &mask);

@@ -890,10 +917,27 @@
      OopMapCache::compute_one_oop_map(m, bci, &mask);
    }
    mask.iterate_oop(&blk);
  }
  
+ void frame::buffered_values_interpreted_do(BufferedValueClosure* f) {
+   assert(is_interpreted_frame(), "Not an interpreted frame");
+   Thread *thread = Thread::current();
+   methodHandle m (thread, interpreter_frame_method());
+   jint      bci = interpreter_frame_bci();
+ 
+   assert(m->is_method(), "checking frame value");
+   assert(!m->is_native() && bci >= 0 && bci < m->code_size(),
+          "invalid bci value");
+ 
+   InterpreterFrameClosure blk(this, m->max_locals(), m->max_stack(), NULL, f);
+ 
+   // process locals & expression stack
+   InterpreterOopMap mask;
+   m->mask_for(bci, &mask);
+   mask.iterate_oop(&blk);
+ }
  
  void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) const {
    InterpretedArgumentOopFinder finder(signature, has_receiver, this, f);
    finder.oops_do();
  }

@@ -937,10 +981,11 @@
    }
  
    virtual void handle_oop_offset() {
      // Extract low order register number from register array.
      // In LP64-land, the high-order bits are valid but unhelpful.
+     assert(_offset < _arg_size, "out of bounds");
      VMReg reg = _regs[_offset].first();
      oop *loc = _fr.oopmapreg_to_oop_location(reg, _reg_map);
      assert(loc != NULL, "missing register map entry");
      _f->do_oop(loc);
    }

@@ -954,15 +999,11 @@
      _offset    = 0;
      _has_receiver = has_receiver;
      _has_appendix = has_appendix;
      _fr        = fr;
      _reg_map   = (RegisterMap*)reg_map;
-     _arg_size  = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0) + (has_appendix ? 1 : 0);
- 
-     int arg_size;
-     _regs = SharedRuntime::find_callee_arguments(signature, has_receiver, has_appendix, &arg_size);
-     assert(arg_size == _arg_size, "wrong arg size");
+     _regs = SharedRuntime::find_callee_arguments(signature, has_receiver, has_appendix, &_arg_size);
    }
  
    void oops_do() {
      if (_has_receiver) {
        handle_oop_offset();
< prev index next >