< prev index next >

src/hotspot/share/code/dependencies.cpp

Print this page

        

@@ -28,10 +28,12 @@
 #include "ci/ciKlass.hpp"
 #include "ci/ciMethod.hpp"
 #include "classfile/javaClasses.inline.hpp"
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/compileTask.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"

@@ -618,10 +620,76 @@
 
 void Dependencies::check_valid_dependency_type(DepType dept) {
   guarantee(FIRST_TYPE <= dept && dept < TYPE_LIMIT, "invalid dependency type: %d", (int) dept);
 }
 
+Dependencies::DepType Dependencies::validate_dependencies(CompileTask* task, bool counter_changed, char** failure_detail) {
+  // First, check non-klass dependencies as we might return early and
+  // not check klass dependencies if the system dictionary
+  // modification counter hasn't changed (see below).
+  for (Dependencies::DepStream deps(this); deps.next(); ) {
+    if (deps.is_klass_type())  continue;  // skip klass dependencies
+    Klass* witness = deps.check_dependency();
+    if (witness != NULL) {
+      return deps.type();
+    }
+  }
+
+  // Klass dependencies must be checked when the system dictionary
+  // changes.  If logging is enabled all violated dependences will be
+  // recorded in the log.  In debug mode check dependencies even if
+  // the system dictionary hasn't changed to verify that no invalid
+  // dependencies were inserted.  Any violated dependences in this
+  // case are dumped to the tty.
+  if (!counter_changed && !trueInDebug) {
+    return end_marker;
+  }
+
+  int klass_violations = 0;
+  DepType result = end_marker;
+  for (Dependencies::DepStream deps(this); deps.next(); ) {
+    if (!deps.is_klass_type())  continue;  // skip non-klass dependencies
+    Klass* witness = deps.check_dependency();
+    if (witness != NULL) {
+      if (klass_violations == 0) {
+        result = deps.type();
+        if (failure_detail != NULL && klass_violations == 0) {
+          // Use a fixed size buffer to prevent the string stream from
+          // resizing in the context of an inner resource mark.
+          char* buffer = NEW_RESOURCE_ARRAY(char, O_BUFLEN);
+          stringStream st(buffer, O_BUFLEN);
+          deps.print_dependency(witness, true, &st);
+          *failure_detail = st.as_string();
+        }
+      }
+      klass_violations++;
+      if (!counter_changed) {
+        // Dependence failed but counter didn't change.  Log a message
+        // describing what failed and allow the assert at the end to
+        // trigger.
+        deps.print_dependency(witness);
+      } else if (xtty == NULL) {
+        // If we're not logging then a single violation is sufficient,
+        // otherwise we want to log all the dependences which were
+        // violated.
+        break;
+      }
+    }
+  }
+
+  if (klass_violations != 0) {
+#ifdef ASSERT
+    if (task != NULL && !counter_changed && !PrintCompilation) {
+      // Print out the compile task that failed
+      task->print_tty();
+    }
+#endif
+    assert(counter_changed, "failed dependencies, but counter didn't change");
+  }
+  return result;
+}
+
 // for the sake of the compiler log, print out current dependencies:
 void Dependencies::log_all_dependencies() {
   if (log() == NULL)  return;
   ResourceMark rm;
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
< prev index next >