< prev index next >

src/share/vm/code/dependencies.cpp

Print this page

        

@@ -24,31 +24,40 @@
 
 #include "precompiled.hpp"
 #include "ci/ciArrayKlass.hpp"
 #include "ci/ciEnv.hpp"
 #include "ci/ciKlass.hpp"
+#include "ci/ciField.hpp"
 #include "ci/ciMethod.hpp"
 #include "classfile/javaClasses.inline.hpp"
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/perfData.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/copy.hpp"
 
-
 #ifdef ASSERT
 static bool must_be_in_vm() {
   Thread* thread = Thread::current();
   if (thread->is_Java_thread())
     return ((JavaThread*)thread)->thread_state() == _thread_in_vm;
   else
     return true;  //something like this: thread->is_VM_thread();
 }
 #endif //ASSERT
 
+// Globals
+
+PerfCounter*    Dependencies::_perf_dependency_checking_time = NULL;
+PerfCounter*    Dependencies::_perf_dependencies_checked_count = NULL;
+PerfCounter*    Dependencies::_perf_dependencies_invalidated = NULL;
+PerfCounter*    Dependencies::_perf_dependencies_total_count = NULL;
+PerfCounter*    Dependencies::_perf_dependencies_context_traversals = NULL;
+
 void Dependencies::initialize(ciEnv* env) {
   Arena* arena = env->arena();
   _oop_recorder = env->oop_recorder();
   _log = env->log();
   _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);

@@ -118,10 +127,24 @@
 
 void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
   assert_common_2(call_site_target_value, call_site, method_handle);
 }
 
+void Dependencies::assert_constant_field_value_klass(ciField* field, ciKlass* ctxk) {
+  // FIXME: how to record a field? no metadata associated; offset is int
+  assert_common_1(constant_field_value_klass, ctxk /*, field*/);
+}
+
+void Dependencies::assert_constant_field_value_instance(ciField* field, ciObject* obj) {
+  if (field->holder()->set_finals()) {
+    // FIXME: how to record a field? no metadata associated; offset is int
+    assert_common_2(constant_field_value_instance, field->holder(), /*field,*/ obj);
+  } else {
+    assert_constant_field_value_klass(field, field->holder());
+  }
+}
+
 // Helper function.  If we are adding a new dep. under ctxk2,
 // try to find an old dep. under a broader* ctxk1.  If there is
 //
 bool Dependencies::maybe_merge_ctxk(GrowableArray<ciBaseObject*>* deps,
                                     int ctxk_i, ciKlass* ctxk2) {

@@ -370,11 +393,13 @@
   "concrete_with_no_concrete_subtype",
   "unique_concrete_method",
   "abstract_with_exclusive_concrete_subtypes_2",
   "exclusive_concrete_methods_2",
   "no_finalizable_subclasses",
-  "call_site_target_value"
+  "call_site_target_value",
+  "constant_field_value_instance",
+  "constant_field_value_klass"
 };
 
 int Dependencies::_dep_args[TYPE_LIMIT] = {
   -1,// end_marker
   1, // evol_method m

@@ -384,11 +409,13 @@
   1, // concrete_with_no_concrete_subtype ctxk
   2, // unique_concrete_method ctxk, m
   3, // unique_concrete_subtypes_2 ctxk, k1, k2
   3, // unique_concrete_methods_2 ctxk, m1, m2
   1, // no_finalizable_subclasses ctxk
-  2  // call_site_target_value call_site, method_handle
+  2, // call_site_target_value call_site, method_handle
+  2, // constant_field_value_instance ctxk oop
+  1  // constant_field_value_klass ctxk
 };
 
 const char* Dependencies::dep_name(Dependencies::DepType dept) {
   if (!dept_in_mask(dept, all_types))  return "?bad-dep?";
   return _dep_name[dept];

@@ -1529,10 +1556,26 @@
     }
   }
   return NULL;  // assertion still valid
 }
 
+void Dependencies::invalidate_dependent_nmethods(instanceKlassHandle ctxk, DepChange& changes, TRAPS) {
+  MutexLocker mu(Compile_lock, THREAD);
+
+  int marked = 0;
+  {
+    MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    marked = ctxk->mark_dependent_nmethods(changes);
+  }
+  if (marked > 0) {
+    ctxk->set_finals(true);
+    // At least one nmethod has been marked for deoptimization
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+}
+
 void Dependencies::DepStream::trace_and_log_witness(Klass* witness) {
   if (witness != NULL) {
     if (TraceDependencies) {
       print_dependency(witness, /*verbose=*/ true);
     }

@@ -1609,16 +1652,41 @@
 
   // Handle CallSite dependency
   if (changes.is_call_site_change())
     return check_call_site_dependency(changes.as_call_site_change());
 
+  if (changes.is_constant_field_change()) {
+    Handle holder = changes.as_constant_field_change()->holder();
+    int offset = changes.as_constant_field_change()->offset();
+    int dep_offset = -1; // TODO: store offset in dependency
+    switch (type()) {
+      case constant_field_value_instance:
+        if (holder.is_null())        return context_type(); // all oops
+        if (holder() == argument_oop(1)) {
+          if (offset == -1)          return context_type(); // all fields
+          if (offset == dep_offset)  return context_type(); // same field
+        }
+        break;
+      case constant_field_value_klass:
+        if (offset == -1)          return context_type(); // all fields
+        if (offset == dep_offset)  return context_type(); // same field
+        break;
+    }
+  }
+
   // irrelevant dependency; skip it
   return NULL;
 }
 
 
 void DepChange::print() {
+  if (is_klass_change())
+    tty->print_cr("klass_change");
+  if (is_call_site_change())
+    tty->print_cr("call_site_change");
+  if (is_constant_field_change())
+    tty->print_cr("constant_field_change: offset=%d %s", as_constant_field_change()->offset(), as_constant_field_change()->holder()->print_string());
   int nsup = 0, nint = 0;
   for (ContextStream str(*this); str.next(); ) {
     Klass* k = str.klass();
     switch (str.change_type()) {
     case Change_new_type:
< prev index next >