< prev index next >

src/hotspot/share/prims/jvmtiImpl.cpp

Print this page
rev 60137 : 8227745: Enable Escape Analysis for Better Performance in the Presence of JVMTI Agents
Reviewed-by: mdoerr, goetz

@@ -439,10 +439,11 @@
   , _depth(depth)
   , _index(index)
   , _type(type)
   , _jvf(NULL)
   , _set(false)
+  , _eb(NULL, NULL, false) // no references escape
   , _result(JVMTI_ERROR_NONE)
 {
 }
 
 // Constructor for object or non-object setter

@@ -453,10 +454,11 @@
   , _index(index)
   , _type(type)
   , _value(value)
   , _jvf(NULL)
   , _set(true)
+  , _eb(JavaThread::current(), thread, type == T_OBJECT)
   , _result(JVMTI_ERROR_NONE)
 {
 }
 
 // Constructor for object getter

@@ -466,10 +468,11 @@
   , _depth(depth)
   , _index(index)
   , _type(T_OBJECT)
   , _jvf(NULL)
   , _set(false)
+  , _eb(calling_thread, thread, true)
   , _result(JVMTI_ERROR_NONE)
 {
 }
 
 vframe *VM_GetOrSetLocal::get_vframe() {

@@ -641,10 +644,54 @@
 
 static bool can_be_deoptimized(vframe* vf) {
   return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
 }
 
+// Revert optimizations based on escape analysis if this is an access to a local object
+bool VM_GetOrSetLocal::deoptimize_objects(javaVFrame* jvf) {
+#if COMPILER2_OR_JVMCI
+  if (NOT_JVMCI(DoEscapeAnalysis &&) _type == T_OBJECT) {
+    if (_depth < _thread->frames_to_pop_failed_realloc()) {
+      // cannot access frame with failed reallocations
+      _result = JVMTI_ERROR_OUT_OF_MEMORY;
+      return false;
+    }
+    if (can_be_deoptimized(jvf)) {
+      compiledVFrame* cf = compiledVFrame::cast(jvf);
+      if (cf->not_global_escape_in_scope() && !_eb.deoptimize_objects(cf->fr().id())) {
+        // reallocation of scalar replaced objects failed, because heap is exhausted
+        _result = JVMTI_ERROR_OUT_OF_MEMORY;
+        return false;
+      }
+    }
+
+    // With this access the object could escape the thread changing its escape state from ArgEscape,
+    // to GlobalEscape so we must deoptimize callers which could have optimized on the escape state.
+    vframe* vf = jvf;
+    do {
+      // move to next physical frame
+      while(!vf->is_top()) {
+        vf = vf->sender();
+      }
+      vf = vf->sender();
+
+      if (vf != NULL && vf->is_compiled_frame()) {
+        compiledVFrame* cvf = compiledVFrame::cast(vf);
+        // Deoptimize objects if arg escape is being passed down the stack.
+        // Note that deoptimizing the frame is not enough, because objects need to be relocked
+        if (cvf->arg_escape() && !_eb.deoptimize_objects(cvf->fr().id())) {
+          // reallocation of scalar replaced objects failed, because heap is exhausted
+          _result = JVMTI_ERROR_OUT_OF_MEMORY;
+          return false;
+        }
+      }
+    } while(vf != NULL && !vf->is_entry_frame());
+  }
+#endif // COMPILER2_OR_JVMCI
+  return true;
+}
+
 bool VM_GetOrSetLocal::doit_prologue() {
   _jvf = get_java_vframe();
   NULL_CHECK(_jvf, false);
 
   Method* method_oop = _jvf->method();

@@ -662,13 +709,18 @@
   }
 
   if (!check_slot_type_no_lvt(_jvf)) {
     return false;
   }
-  if (method_oop->has_localvariable_table()) {
-    return check_slot_type_lvt(_jvf);
+  if (method_oop->has_localvariable_table() && !check_slot_type_lvt(_jvf)) {
+    return false;
   }
+
+  if (!deoptimize_objects(_jvf)) {
+    return false;
+  }
+
   return true;
 }
 
 void VM_GetOrSetLocal::doit() {
   InterpreterOopMap oop_mask;
< prev index next >