src/share/vm/code/dependencies.cpp

Print this page

        

*** 28,37 **** --- 28,38 ---- #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,173 **** _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); } _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_leaf_type(ciKlass* ctxk) { ! if (ctxk->is_array_klass()) { // 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(); //if (ctxk->is_final()) return; // Ex: String[][] } check_ctxk(ctxk); ! assert_common_1(leaf_type, ctxk); } ! void Dependencies::assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck) { check_ctxk_abstract(ctxk); ! assert_common_2(abstract_with_unique_concrete_subtype, ctxk, conck); } ! void Dependencies::assert_abstract_with_no_concrete_subtype(ciKlass* ctxk) { check_ctxk_abstract(ctxk); ! assert_common_1(abstract_with_no_concrete_subtype, ctxk); } ! void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) { check_ctxk_concrete(ctxk); ! assert_common_1(concrete_with_no_concrete_subtype, ctxk); } ! void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) { check_ctxk(ctxk); ! assert_common_2(unique_concrete_method, ctxk, uniqm); } ! void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2) { check_ctxk(ctxk); ! assert_common_3(abstract_with_exclusive_concrete_subtypes_2, ctxk, k1, k2); } ! void Dependencies::assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2) { check_ctxk(ctxk); ! assert_common_3(exclusive_concrete_methods_2, ctxk, m1, m2); } ! void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { check_ctxk(ctxk); ! assert_common_1(no_finalizable_subclasses, 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); } // 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(); 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); return true; } else { return false; } } ! void Dependencies::assert_common_1(DepType dept, ciBaseObject* x) { assert(dep_args(dept) == 1, "sanity"); log_dependency(dept, x); ! GrowableArray<ciBaseObject*>* 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) { assert(dep_args(dept) == 2, "sanity"); log_dependency(dept, x0, x1); ! GrowableArray<ciBaseObject*>* 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); if (x1 == y1) { // same subject; check the context ! if (maybe_merge_ctxk(deps, i+0, x0->as_metadata()->as_klass())) { return; } } } } --- 51,178 ---- _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<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(Method* m) { ! assert_common_1(evol_method, DepValue(_oop_recorder, m)); } ! 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. ! 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, DepValue(_oop_recorder, ctxk)); } ! void Dependencies::assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck) { check_ctxk_abstract(ctxk); ! 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(Klass* ctxk) { check_ctxk_abstract(ctxk); ! assert_common_1(abstract_with_no_concrete_subtype, DepValue(_oop_recorder, ctxk)); } ! void Dependencies::assert_concrete_with_no_concrete_subtype(Klass* ctxk) { check_ctxk_concrete(ctxk); ! assert_common_1(concrete_with_no_concrete_subtype, DepValue(_oop_recorder, ctxk)); } ! void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) { check_ctxk(ctxk); ! assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm)); } ! void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(Klass* ctxk, Klass* k1, Klass* k2) { check_ctxk(ctxk); ! 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(Klass* ctxk, Method* m1, Method* m2) { check_ctxk(ctxk); ! 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(Klass* ctxk) { check_ctxk(ctxk); ! assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk)); } ! 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<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, DepValue(_oop_recorder, ctxk2)); return true; } else { return false; } } ! void Dependencies::assert_common_1(DepType dept, DepValue x) { assert(dep_args(dept) == 1, "sanity"); log_dependency(dept, x); ! 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, ! DepValue x0, DepValue x1) { assert(dep_args(dept) == 2, "sanity"); log_dependency(dept, x0, x1); ! 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; ) { ! DepValue y1 = deps->at(i+1); if (x1 == y1) { // same subject; check the context ! if (maybe_merge_ctxk(deps, i+0, x0.as_klass(_oop_recorder))) { return; } } } }
*** 175,186 **** 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); if (x0 == y0 && x1 == y1) { return; } } } --- 180,191 ---- 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; ) { ! DepValue y0 = deps->at(i+0); ! DepValue y1 = deps->at(i+1); if (x0 == y0 && x1 == y1) { return; } } }
*** 190,233 **** deps->append(x0); deps->append(x1); } void Dependencies::assert_common_3(DepType dept, ! ciKlass* ctxk, ciBaseObject* x, ciBaseObject* 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]; // 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); break; case exclusive_concrete_methods_2: ! swap = (x->ident() > x2->ident() && x->as_metadata()->as_method()->holder() != ctxk); break; } ! if (swap) { ciBaseObject* 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); 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(x); deps->append(x2); } /// Support for encoding dependencies into an nmethod: --- 195,238 ---- deps->append(x0); deps->append(x1); } void Dependencies::assert_common_3(DepType dept, ! Klass* ctxk, DepValue x, DepValue x2) { assert(dep_context_arg(dept) == 0, "sanity"); assert(dep_args(dept) == 3, "sanity"); ! 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.index() > x2.index() && x.as_klass(_oop_recorder) != ctxk); break; case exclusive_concrete_methods_2: ! swap = (x.index() > x2.index() && x.as_method(_oop_recorder)->method_holder() != ctxk); break; } ! 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; ) { ! 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(DepValue(_oop_recorder, ctxk)); deps->append(x); deps->append(x2); } /// Support for encoding dependencies into an nmethod:
*** 240,267 **** (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) { for (int i = 0; i < narg; i++) { ! int diff = p1[i]->ident() - p2[i]->ident(); if (diff != 0) return diff; } return 0; } ! static int sort_dep_arg_1(ciBaseObject** p1, ciBaseObject** p2) { return sort_dep(p1, p2, 1); } ! static int sort_dep_arg_2(ciBaseObject** p1, ciBaseObject** p2) { return sort_dep(p1, p2, 2); } ! static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** 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]; 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; --- 245,272 ---- (HeapWord*) beg, size_in_bytes() / sizeof(HeapWord)); assert(size_in_bytes() % sizeof(HeapWord) == 0, "copy by words"); } ! static int sort_dep(Dependencies::DepValue* p1, Dependencies::DepValue* p2, int narg) { for (int i = 0; i < narg; i++) { ! int diff = p1[i].sort_key() - p2[i].sort_key(); if (diff != 0) return diff; } return 0; } ! static int sort_dep_arg_1(Dependencies::DepValue* p1, Dependencies::DepValue* p2) { return sort_dep(p1, p2, 1); } ! static int sort_dep_arg_2(Dependencies::DepValue* p1, Dependencies::DepValue* p2) { return sort_dep(p1, p2, 2); } ! 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<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,294 **** 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]; est_size += deps->length()*2; // tags and argument(s) } return est_size; } ! ciKlass* Dependencies::ctxk_encoded_as_null(DepType dept, ciBaseObject* x) { switch (dept) { case abstract_with_exclusive_concrete_subtypes_2: ! return x->as_metadata()->as_klass(); case unique_concrete_method: case exclusive_concrete_methods_2: ! return x->as_metadata()->as_method()->holder(); } return NULL; // let NULL be NULL } Klass* Dependencies::ctxk_encoded_as_null(DepType dept, Metadata* x) { --- 277,299 ---- 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<DepValue>* deps = _deps[dept]; est_size += deps->length()*2; // tags and argument(s) } return est_size; } ! 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_klass(oop_recorder); case unique_concrete_method: case exclusive_concrete_methods_2: ! 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,347 **** // 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]; 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)) { 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()); ! } bytes.write_int(idx); } } } --- 316,346 ---- // 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<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) { ! 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; ! DepValue v = deps->at(i+j); ! int idx = v.index(); bytes.write_int(idx); } } }
*** 404,417 **** } // 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]; for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { DepType dept = (DepType)deptv; ! GrowableArray<ciBaseObject*>* 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 --- 403,416 ---- } // for the sake of the compiler log, print out current dependencies: void Dependencies::log_all_dependencies() { if (log() == NULL) return; ! DepValue args[max_arg_count]; for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { DepType dept = (DepType)deptv; ! 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,431 **** --- 421,450 ---- } } 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; }