< prev index next >

src/share/vm/code/dependencies.cpp

Print this page

        

*** 29,38 **** --- 29,39 ---- #include "ci/ciMethod.hpp" #include "classfile/javaClasses.inline.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 "runtime/thread.inline.hpp" #include "utilities/copy.hpp"
*** 50,59 **** --- 51,63 ---- 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); + #if INCLUDE_JVMCI + _using_dep_values = false; + #endif 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;
*** 118,127 **** --- 122,191 ---- void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) { assert_common_2(call_site_target_value, call_site, method_handle); } + #if INCLUDE_JVMCI + + Dependencies::Dependencies(Arena* arena, OopRecorder* oop_recorder, CompileLog* log) { + _oop_recorder = oop_recorder; + _log = log; + _dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0); + _using_dep_values = true; + DEBUG_ONLY(_dep_values[end_marker] = NULL); + for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) { + _dep_values[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_has_no_finalizable_subclasses(Klass* ctxk) { + check_ctxk(ctxk); + assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk)); + } + + 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); + DepValue conck_dv(_oop_recorder, conck, &ctxk_dv); + assert_common_2(abstract_with_unique_concrete_subtype, ctxk_dv, conck_dv); + } + + 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_call_site_target_value(oop call_site, oop method_handle) { + assert_common_2(call_site_target_value, DepValue(_oop_recorder, JNIHandles::make_local(call_site)), DepValue(_oop_recorder, JNIHandles::make_local(method_handle))); + } + + #endif // INCLUDE_JVMCI + + // 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) {
*** 228,237 **** --- 292,373 ---- deps->append(ctxk); deps->append(x); deps->append(x2); } + #if INCLUDE_JVMCI + bool Dependencies::maybe_merge_ctxk(GrowableArray<DepValue>* deps, + int ctxk_i, DepValue ctxk2_dv) { + Klass* ctxk1 = deps->at(ctxk_i).as_klass(_oop_recorder); + Klass* ctxk2 = ctxk2_dv.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_dv); + 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 = _dep_values[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 = _dep_values[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)) { + return; + } + } + } + } + } else { + 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; + } + } + } + } + + // append the assertion in the correct bucket: + deps->append(x0); + deps->append(x1); + } + #endif // INCLUDE_JVMCI + /// Support for encoding dependencies into an nmethod: void Dependencies::copy_to(nmethod* nm) { address beg = nm->dependencies_begin(); address end = nm->dependencies_end();
*** 254,264 **** --- 390,433 ---- 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); } + #if INCLUDE_JVMCI + // metadata deps are sorted before object deps + static int sort_dep_value(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_value_arg_1(Dependencies::DepValue* p1, Dependencies::DepValue* p2) + { return sort_dep_value(p1, p2, 1); } + static int sort_dep_value_arg_2(Dependencies::DepValue* p1, Dependencies::DepValue* p2) + { return sort_dep_value(p1, p2, 2); } + static int sort_dep_value_arg_3(Dependencies::DepValue* p1, Dependencies::DepValue* p2) + { return sort_dep_value(p1, p2, 3); } + #endif // INCLUDE_JVMCI + void Dependencies::sort_all_deps() { + #if INCLUDE_JVMCI + if (_using_dep_values) { + for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { + DepType dept = (DepType)deptv; + GrowableArray<DepValue>* deps = _dep_values[dept]; + if (deps->length() <= 1) continue; + switch (dep_args(dept)) { + case 1: deps->sort(sort_dep_value_arg_1, 1); break; + case 2: deps->sort(sort_dep_value_arg_2, 2); break; + case 3: deps->sort(sort_dep_value_arg_3, 3); break; + default: ShouldNotReachHere(); + } + } + return; + } + #endif // INCLUDE_JVMCI 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)) {
*** 270,279 **** --- 439,458 ---- } } size_t Dependencies::estimate_size_in_bytes() { size_t est_size = 100; + #if INCLUDE_JVMCI + if (_using_dep_values) { + for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { + DepType dept = (DepType)deptv; + GrowableArray<DepValue>* deps = _dep_values[dept]; + est_size += deps->length() * 2; // tags and argument(s) + } + return est_size; + } + #endif // INCLUDE_JVMCI 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) }
*** 309,318 **** --- 488,528 ---- sort_all_deps(); // cast is safe, no deps can overflow INT_MAX CompressedWriteStream bytes((int)estimate_size_in_bytes()); + #if INCLUDE_JVMCI + if (_using_dep_values) { + for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { + DepType dept = (DepType)deptv; + GrowableArray<DepValue>* deps = _dep_values[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(dept, x.as_metadata(_oop_recorder))) { + 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); + } + } + } + } else { + #endif // INCLUDE_JVMCI 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);
*** 342,351 **** --- 552,564 ---- } bytes.write_int(idx); } } } + #if INCLUDE_JVMCI + } + #endif // write a sentinel byte to mark the end bytes.write_byte(end_marker); // round it out to a word boundary
*** 538,551 **** } xtty->end_elem(); } void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args, ! Klass* witness) { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block ! tty->print_cr("%s of type %s", (witness == NULL)? "Dependency": "Failed dependency", dep_name(dept)); // print arguments int ctxkj = dep_context_arg(dept); // -1 if no context arg for (int j = 0; j < args->length(); j++) { --- 751,764 ---- } xtty->end_elem(); } void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args, ! Klass* witness, outputStream* st) { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block ! st->print_cr("%s of type %s", (witness == NULL)? "Dependency": "Failed dependency", dep_name(dept)); // print arguments int ctxkj = dep_context_arg(dept); // -1 if no context arg for (int j = 0; j < args->length(); j++) {
*** 563,588 **** } else if (arg.is_klass()) { what = "class "; } else { what = "object "; } ! tty->print(" %s = %s", what, (put_star? "*": "")); if (arg.is_klass()) { ! tty->print("%s", ((Klass*)arg.metadata_value())->external_name()); } else if (arg.is_method()) { ! ((Method*)arg.metadata_value())->print_value(); } else if (arg.is_oop()) { ! arg.oop_value()->print_value_on(tty); } else { ShouldNotReachHere(); // Provide impl for this type. } ! tty->cr(); } if (witness != NULL) { bool put_star = !Dependencies::is_concrete_klass(witness); ! tty->print_cr(" witness = %s%s", (put_star? "*": ""), witness->external_name()); } } --- 776,801 ---- } else if (arg.is_klass()) { what = "class "; } else { what = "object "; } ! st->print(" %s = %s", what, (put_star? "*": "")); if (arg.is_klass()) { ! st->print("%s", ((Klass*)arg.metadata_value())->external_name()); } else if (arg.is_method()) { ! ((Method*)arg.metadata_value())->print_value_on(st); } else if (arg.is_oop()) { ! arg.oop_value()->print_value_on(st); } else { ShouldNotReachHere(); // Provide impl for this type. } ! st->cr(); } if (witness != NULL) { bool put_star = !Dependencies::is_concrete_klass(witness); ! st->print_cr(" witness = %s%s", (put_star? "*": ""), witness->external_name()); } }
*** 598,615 **** args->push(argument(j)); } } int argslen = args->length(); if (_deps != NULL && _deps->log() != NULL) { Dependencies::write_dependency_to(_deps->log(), type(), args, witness); } else { Dependencies::write_dependency_to(xtty, type(), args, witness); } guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } ! void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) { ResourceMark rm; int nargs = argument_count(); GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs); for (int j = 0; j < nargs; j++) { if (is_oop_argument(j)) { --- 811,833 ---- args->push(argument(j)); } } int argslen = args->length(); if (_deps != NULL && _deps->log() != NULL) { + if (ciEnv::current() != NULL) { Dependencies::write_dependency_to(_deps->log(), type(), args, witness); } else { + // Treat the CompileLog as an xmlstream instead + Dependencies::write_dependency_to((xmlStream*)_deps->log(), type(), args, witness); + } + } else { Dependencies::write_dependency_to(xtty, type(), args, witness); } guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } ! void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose, outputStream* st) { ResourceMark rm; int nargs = argument_count(); GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs); for (int j = 0; j < nargs; j++) { if (is_oop_argument(j)) {
*** 617,632 **** } else { args->push(argument(j)); } } int argslen = args->length(); ! Dependencies::print_dependency(type(), args, witness); if (verbose) { if (_code != NULL) { ! tty->print(" code: "); ! _code->print_value_on(tty); ! tty->cr(); } } guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } --- 835,850 ---- } else { args->push(argument(j)); } } int argslen = args->length(); ! Dependencies::print_dependency(type(), args, witness, st); if (verbose) { if (_code != NULL) { ! st->print(" code: "); ! _code->print_value_on(st); ! st->cr(); } } guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); }
< prev index next >