src/share/vm/code/dependencies.cpp

Print this page

        

@@ -28,10 +28,11 @@
 #include "ci/ciKlass.hpp"
 #include "ci/ciMethod.hpp"
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
 #include "utilities/copy.hpp"
 
 

@@ -50,124 +51,128 @@
   _oop_recorder = env->oop_recorder();
   _log = env->log();
   _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
   DEBUG_ONLY(_deps[end_marker] = NULL);
   for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
-    _deps[i] = new(arena) GrowableArray<ciBaseObject*>(arena, 10, 0, 0);
+    _deps[i] = new(arena) GrowableArray<DepValue>(arena, 10, 0, DepValue());
   }
   _content_bytes = NULL;
   _size_in_bytes = (size_t)-1;
 
   assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT), "sanity");
 }
 
-void Dependencies::assert_evol_method(ciMethod* m) {
-  assert_common_1(evol_method, m);
+void Dependencies::assert_evol_method(Method* m) {
+  assert_common_1(evol_method, DepValue(_oop_recorder, m));
 }
 
-void Dependencies::assert_leaf_type(ciKlass* ctxk) {
-  if (ctxk->is_array_klass()) {
+void Dependencies::assert_leaf_type(Klass* ctxk) {
+  if (ctxk->oop_is_array()) {
     // As a special case, support this assertion on an array type,
     // which reduces to an assertion on its element type.
     // Note that this cannot be done with assertions that
     // relate to concreteness or abstractness.
-    ciType* elemt = ctxk->as_array_klass()->base_element_type();
-    if (!elemt->is_instance_klass())  return;   // Ex:  int[][]
-    ctxk = elemt->as_instance_klass();
+    BasicType elemt = ArrayKlass::cast(ctxk)->element_type();
+    if (is_java_primitive(elemt))  return;   // Ex:  int[][]
+    ctxk = ObjArrayKlass::cast(ctxk)->bottom_klass();
     //if (ctxk->is_final())  return;            // Ex:  String[][]
   }
   check_ctxk(ctxk);
-  assert_common_1(leaf_type, ctxk);
+  assert_common_1(leaf_type, DepValue(_oop_recorder, ctxk));
 }
 
-void Dependencies::assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck) {
+void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck) {
   check_ctxk_abstract(ctxk);
-  assert_common_2(abstract_with_unique_concrete_subtype, ctxk, conck);
+  DepValue ctxk_dv(_oop_recorder, ctxk);
+  assert_common_2(abstract_with_unique_concrete_subtype, ctxk_dv, DepValue(_oop_recorder, conck, &ctxk_dv));
 }
 
-void Dependencies::assert_abstract_with_no_concrete_subtype(ciKlass* ctxk) {
+void Dependencies::assert_abstract_with_no_concrete_subtype(Klass* ctxk) {
   check_ctxk_abstract(ctxk);
-  assert_common_1(abstract_with_no_concrete_subtype, ctxk);
+  assert_common_1(abstract_with_no_concrete_subtype, DepValue(_oop_recorder, ctxk));
 }
 
-void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) {
+void Dependencies::assert_concrete_with_no_concrete_subtype(Klass* ctxk) {
   check_ctxk_concrete(ctxk);
-  assert_common_1(concrete_with_no_concrete_subtype, ctxk);
+  assert_common_1(concrete_with_no_concrete_subtype, DepValue(_oop_recorder, ctxk));
 }
 
-void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) {
+void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) {
   check_ctxk(ctxk);
-  assert_common_2(unique_concrete_method, ctxk, uniqm);
+  assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
 }
 
-void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2) {
+void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(Klass* ctxk, Klass* k1, Klass* k2) {
   check_ctxk(ctxk);
-  assert_common_3(abstract_with_exclusive_concrete_subtypes_2, ctxk, k1, k2);
+  DepValue k1_dv(_oop_recorder, k1);
+  assert_common_3(abstract_with_exclusive_concrete_subtypes_2, ctxk, k1_dv, DepValue(_oop_recorder, k2, &k1_dv));
 }
 
-void Dependencies::assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2) {
+void Dependencies::assert_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2) {
   check_ctxk(ctxk);
-  assert_common_3(exclusive_concrete_methods_2, ctxk, m1, m2);
+  DepValue m1_dv(_oop_recorder, m1);
+  assert_common_3(exclusive_concrete_methods_2, ctxk, m1_dv, DepValue(_oop_recorder, m2, &m1_dv));
 }
 
-void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) {
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
   check_ctxk(ctxk);
-  assert_common_1(no_finalizable_subclasses, ctxk);
+  assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
 }
 
-void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
-  check_ctxk(call_site->klass());
-  assert_common_2(call_site_target_value, call_site, method_handle);
+void Dependencies::assert_call_site_target_value(jobject call_site, jobject method_handle) {
+  Klass* ctxk = JNIHandles::resolve(call_site)->klass();
+  check_ctxk(ctxk);
+  assert_common_2(call_site_target_value, DepValue(_oop_recorder, call_site), DepValue(_oop_recorder, method_handle));
 }
 
 // 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) {
-  ciKlass* ctxk1 = deps->at(ctxk_i)->as_metadata()->as_klass();
+bool Dependencies::maybe_merge_ctxk(GrowableArray<DepValue>* deps,
+                                    int ctxk_i, Klass* ctxk2) {
+  Klass* ctxk1 = deps->at(ctxk_i).as_klass(_oop_recorder);
   if (ctxk2->is_subtype_of(ctxk1)) {
     return true;  // success, and no need to change
   } else if (ctxk1->is_subtype_of(ctxk2)) {
     // new context class fully subsumes previous one
-    deps->at_put(ctxk_i, ctxk2);
+    deps->at_put(ctxk_i, DepValue(_oop_recorder, ctxk2));
     return true;
   } else {
     return false;
   }
 }
 
-void Dependencies::assert_common_1(DepType dept, ciBaseObject* x) {
+void Dependencies::assert_common_1(DepType dept, DepValue x) {
   assert(dep_args(dept) == 1, "sanity");
   log_dependency(dept, x);
-  GrowableArray<ciBaseObject*>* deps = _deps[dept];
+  GrowableArray<DepValue>* deps = _deps[dept];
 
   // see if the same (or a similar) dep is already recorded
   if (note_dep_seen(dept, x)) {
     assert(deps->find(x) >= 0, "sanity");
   } else {
     deps->append(x);
   }
 }
 
 void Dependencies::assert_common_2(DepType dept,
-                                   ciBaseObject* x0, ciBaseObject* x1) {
+                                   DepValue x0, DepValue x1) {
   assert(dep_args(dept) == 2, "sanity");
   log_dependency(dept, x0, x1);
-  GrowableArray<ciBaseObject*>* deps = _deps[dept];
+  GrowableArray<DepValue>* deps = _deps[dept];
 
   // see if the same (or a similar) dep is already recorded
   bool has_ctxk = has_explicit_context_arg(dept);
   if (has_ctxk) {
     assert(dep_context_arg(dept) == 0, "sanity");
     if (note_dep_seen(dept, x1)) {
       // look in this bucket for redundant assertions
       const int stride = 2;
       for (int i = deps->length(); (i -= stride) >= 0; ) {
-        ciBaseObject* y1 = deps->at(i+1);
+        DepValue y1 = deps->at(i+1);
         if (x1 == y1) {  // same subject; check the context
-          if (maybe_merge_ctxk(deps, i+0, x0->as_metadata()->as_klass())) {
+          if (maybe_merge_ctxk(deps, i+0, x0.as_klass(_oop_recorder))) {
             return;
           }
         }
       }
     }

@@ -175,12 +180,12 @@
     assert(dep_implicit_context_arg(dept) == 0, "sanity");
     if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
       // look in this bucket for redundant assertions
       const int stride = 2;
       for (int i = deps->length(); (i -= stride) >= 0; ) {
-        ciBaseObject* y0 = deps->at(i+0);
-        ciBaseObject* y1 = deps->at(i+1);
+        DepValue y0 = deps->at(i+0);
+        DepValue y1 = deps->at(i+1);
         if (x0 == y0 && x1 == y1) {
           return;
         }
       }
     }

@@ -190,44 +195,44 @@
   deps->append(x0);
   deps->append(x1);
 }
 
 void Dependencies::assert_common_3(DepType dept,
-                                   ciKlass* ctxk, ciBaseObject* x, ciBaseObject* x2) {
+                                   Klass* ctxk, DepValue x, DepValue x2) {
   assert(dep_context_arg(dept) == 0, "sanity");
   assert(dep_args(dept) == 3, "sanity");
-  log_dependency(dept, ctxk, x, x2);
-  GrowableArray<ciBaseObject*>* deps = _deps[dept];
+  log_dependency(dept, DepValue(_oop_recorder, ctxk), x, x2);
+  GrowableArray<DepValue>* deps = _deps[dept];
 
   // try to normalize an unordered pair:
   bool swap = false;
   switch (dept) {
   case abstract_with_exclusive_concrete_subtypes_2:
-    swap = (x->ident() > x2->ident() && x->as_metadata()->as_klass() != ctxk);
+    swap = (x.index() > x2.index() && x.as_klass(_oop_recorder) != ctxk);
     break;
   case exclusive_concrete_methods_2:
-    swap = (x->ident() > x2->ident() && x->as_metadata()->as_method()->holder() != ctxk);
+    swap = (x.index() > x2.index() && x.as_method(_oop_recorder)->method_holder() != ctxk);
     break;
   }
-  if (swap) { ciBaseObject* t = x; x = x2; x2 = t; }
+  if (swap) { DepValue t = x; x = x2; x2 = t; }
 
   // see if the same (or a similar) dep is already recorded
   if (note_dep_seen(dept, x) && note_dep_seen(dept, x2)) {
     // look in this bucket for redundant assertions
     const int stride = 3;
     for (int i = deps->length(); (i -= stride) >= 0; ) {
-      ciBaseObject* y  = deps->at(i+1);
-      ciBaseObject* y2 = deps->at(i+2);
+      DepValue y  = deps->at(i+1);
+      DepValue y2 = deps->at(i+2);
       if (x == y && x2 == y2) {  // same subjects; check the context
         if (maybe_merge_ctxk(deps, i+0, ctxk)) {
           return;
         }
       }
     }
   }
   // append the assertion in the correct bucket:
-  deps->append(ctxk);
+  deps->append(DepValue(_oop_recorder, ctxk));
   deps->append(x);
   deps->append(x2);
 }
 
 /// Support for encoding dependencies into an nmethod:

@@ -240,28 +245,28 @@
                        (HeapWord*) beg,
                        size_in_bytes() / sizeof(HeapWord));
   assert(size_in_bytes() % sizeof(HeapWord) == 0, "copy by words");
 }
 
-static int sort_dep(ciBaseObject** p1, ciBaseObject** p2, int narg) {
+static int sort_dep(Dependencies::DepValue* p1, Dependencies::DepValue* p2, int narg) {
   for (int i = 0; i < narg; i++) {
-    int diff = p1[i]->ident() - p2[i]->ident();
+    int diff = p1[i].sort_key() - p2[i].sort_key();
     if (diff != 0)  return diff;
   }
   return 0;
 }
-static int sort_dep_arg_1(ciBaseObject** p1, ciBaseObject** p2)
+static int sort_dep_arg_1(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
 { return sort_dep(p1, p2, 1); }
-static int sort_dep_arg_2(ciBaseObject** p1, ciBaseObject** p2)
+static int sort_dep_arg_2(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
 { return sort_dep(p1, p2, 2); }
-static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** p2)
+static int sort_dep_arg_3(Dependencies::DepValue* p1, Dependencies::DepValue* p2)
 { return sort_dep(p1, p2, 3); }
 
 void Dependencies::sort_all_deps() {
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
-    GrowableArray<ciBaseObject*>* deps = _deps[dept];
+    GrowableArray<DepValue>* deps = _deps[dept];
     if (deps->length() <= 1)  continue;
     switch (dep_args(dept)) {
     case 1: deps->sort(sort_dep_arg_1, 1); break;
     case 2: deps->sort(sort_dep_arg_2, 2); break;
     case 3: deps->sort(sort_dep_arg_3, 3); break;

@@ -272,23 +277,23 @@
 
 size_t Dependencies::estimate_size_in_bytes() {
   size_t est_size = 100;
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
-    GrowableArray<ciBaseObject*>* deps = _deps[dept];
+    GrowableArray<DepValue>* deps = _deps[dept];
     est_size += deps->length()*2;  // tags and argument(s)
   }
   return est_size;
 }
 
-ciKlass* Dependencies::ctxk_encoded_as_null(DepType dept, ciBaseObject* x) {
+Klass* Dependencies::ctxk_encoded_as_null(OopRecorder* oop_recorder, DepType dept, DepValue x) {
   switch (dept) {
   case abstract_with_exclusive_concrete_subtypes_2:
-    return x->as_metadata()->as_klass();
+    return x.as_klass(oop_recorder);
   case unique_concrete_method:
   case exclusive_concrete_methods_2:
-    return x->as_metadata()->as_method()->holder();
+    return x.as_method(oop_recorder)->method_holder();
   }
   return NULL;  // let NULL be NULL
 }
 
 Klass* Dependencies::ctxk_encoded_as_null(DepType dept, Metadata* x) {

@@ -311,37 +316,31 @@
   // cast is safe, no deps can overflow INT_MAX
   CompressedWriteStream bytes((int)estimate_size_in_bytes());
 
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
-    GrowableArray<ciBaseObject*>* deps = _deps[dept];
+    GrowableArray<DepValue>* deps = _deps[dept];
     if (deps->length() == 0)  continue;
     int stride = dep_args(dept);
     int ctxkj  = dep_context_arg(dept);  // -1 if no context arg
     assert(stride > 0, "sanity");
     for (int i = 0; i < deps->length(); i += stride) {
       jbyte code_byte = (jbyte)dept;
       int skipj = -1;
       if (ctxkj >= 0 && ctxkj+1 < stride) {
-        ciKlass*  ctxk = deps->at(i+ctxkj+0)->as_metadata()->as_klass();
-        ciBaseObject* x     = deps->at(i+ctxkj+1);  // following argument
-        if (ctxk == ctxk_encoded_as_null(dept, x)) {
+        Klass*  ctxk = deps->at(i+ctxkj+0).as_klass(_oop_recorder);
+        DepValue x     = deps->at(i+ctxkj+1);  // following argument
+        if (ctxk == ctxk_encoded_as_null(_oop_recorder, dept, x)) {
           skipj = ctxkj;  // we win:  maybe one less oop to keep track of
           code_byte |= default_context_type_bit;
         }
       }
       bytes.write_byte(code_byte);
       for (int j = 0; j < stride; j++) {
         if (j == skipj)  continue;
-        ciBaseObject* v = deps->at(i+j);
-        int idx;
-        if (v->is_object()) {
-          idx = _oop_recorder->find_index(v->as_object()->constant_encoding());
-        } else {
-          ciMetadata* meta = v->as_metadata();
-          idx = _oop_recorder->find_index(meta->constant_encoding());
-        }
+        DepValue v = deps->at(i+j);
+        int idx = v.index();
         bytes.write_int(idx);
       }
     }
   }
 

@@ -404,14 +403,14 @@
 }
 
 // for the sake of the compiler log, print out current dependencies:
 void Dependencies::log_all_dependencies() {
   if (log() == NULL)  return;
-  ciBaseObject* args[max_arg_count];
+  DepValue args[max_arg_count];
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
-    GrowableArray<ciBaseObject*>* deps = _deps[dept];
+    GrowableArray<DepValue>* deps = _deps[dept];
     if (deps->length() == 0)  continue;
     int stride = dep_args(dept);
     for (int i = 0; i < deps->length(); i += stride) {
       for (int j = 0; j < stride; j++) {
         // flush out the identities before printing

@@ -422,10 +421,30 @@
   }
 }
 
 void Dependencies::write_dependency_to(CompileLog* log,
                                        DepType dept,
+                                       int nargs, DepValue args[],
+                                       Klass* witness) {
+  if (log == NULL) {
+    return;
+  }
+  ciEnv* env = ciEnv::current();
+  ciBaseObject* ciargs[max_arg_count];
+  assert(nargs <= max_arg_count, "oob");
+  for (int j = 0; j < nargs; j++) {
+    if (args[j].is_object()) {
+      ciargs[j] = env->get_object(JNIHandles::resolve(args[j].as_object(_oop_recorder)));
+    } else {
+      ciargs[j] = env->get_metadata(args[j].as_metadata(_oop_recorder));
+    }
+  }
+  Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness);
+}
+
+void Dependencies::write_dependency_to(CompileLog* log,
+                                       DepType dept,
                                        int nargs, DepArgument args[],
                                        Klass* witness) {
   if (log == NULL) {
     return;
   }