src/share/vm/code/dependencies.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/code/dependencies.cpp	Tue Jan 21 16:02:31 2014
--- new/src/share/vm/code/dependencies.cpp	Tue Jan 21 16:02:31 2014

*** 50,173 **** --- 50,172 ---- _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) { ! void Dependencies::assert_evol_method(DepValue m) { assert_common_1(evol_method, m); } ! void Dependencies::assert_leaf_type(ciKlass* ctxk) { ! if (ctxk->is_array_klass()) { ! void Dependencies::assert_leaf_type(DepValue 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_array_element_instance_klass()) return; // Ex: int[][] + ctxk = ctxk.array_element_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) { ! void Dependencies::assert_abstract_with_unique_concrete_subtype(DepValue ctxk, DepValue 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) { ! void Dependencies::assert_abstract_with_no_concrete_subtype(DepValue ctxk) { check_ctxk_abstract(ctxk); assert_common_1(abstract_with_no_concrete_subtype, ctxk); } ! void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) { ! void Dependencies::assert_concrete_with_no_concrete_subtype(DepValue ctxk) { check_ctxk_concrete(ctxk); assert_common_1(concrete_with_no_concrete_subtype, ctxk); } ! void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) { ! void Dependencies::assert_unique_concrete_method(DepValue ctxk, DepValue 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) { ! void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(DepValue ctxk, DepValue k1, DepValue 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) { ! void Dependencies::assert_exclusive_concrete_methods(DepValue ctxk, DepValue m1, DepValue m2) { check_ctxk(ctxk); assert_common_3(exclusive_concrete_methods_2, ctxk, m1, m2); } ! void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { ! void Dependencies::assert_has_no_finalizable_subclasses(DepValue 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()); ! void Dependencies::assert_call_site_target_value(DepValue call_site, DepValue method_handle) { ! check_ctxk(call_site); 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)) { ! bool Dependencies::maybe_merge_ctxk(GrowableArray<DepValue>* deps, ! int ctxk_i, DepValue ctxk2) { ! DepValue ctxk1 = deps->at(ctxk_i); ! if (ctxk2.is_subtype_of(ctxk1)) { return true; // success, and no need to change ! } else if (ctxk1->is_subtype_of(ctxk2)) { ! } 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) { ! 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())) { return; } } } }
*** 175,186 **** --- 174,185 ---- 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,224 **** --- 189,223 ---- deps->append(x0); deps->append(x1); } void Dependencies::assert_common_3(DepType dept, ! ciKlass* ctxk, ciBaseObject* x, ciBaseObject* x2) { ! DepValue 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]; ! 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.ident() > x2.ident() && x != ctxk); break; case exclusive_concrete_methods_2: ! swap = (x->ident() > x2->ident() && x->as_metadata()->as_method()->holder() != ctxk); ! swap = (x.ident() > x2.ident() && x.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; } }
*** 240,267 **** --- 239,266 ---- (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(DepValue* p1, DepValue* p2, int narg) { for (int i = 0; i < narg; i++) { ! int diff = p1[i]->ident() - p2[i]->ident(); ! 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) ! static int sort_dep_arg_1(DepValue* p1, DepValue* p2) { return sort_dep(p1, p2, 1); } ! static int sort_dep_arg_2(ciBaseObject** p1, ciBaseObject** p2) ! static int sort_dep_arg_2(DepValue* p1, DepValue* p2) { return sort_dep(p1, p2, 2); } ! static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** p2) ! static int sort_dep_arg_3(DepValue* p1, 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,294 **** --- 271,293 ---- 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) { ! DepValue Dependencies::ctxk_encoded_as_null(DepType dept, DepValue 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 x.method_holder(); } return NULL; // let NULL be NULL } Klass* Dependencies::ctxk_encoded_as_null(DepType dept, Metadata* x) {
*** 311,348 **** --- 310,340 ---- // 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 ! DepValue ctxk = deps->at(i+ctxkj+0); ! DepValue 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); ! DepValue v = deps->at(i+j); ! bytes.write_int(v.idx(_oop_recorder)); } } } // write a sentinel byte to mark the end
*** 404,417 **** --- 396,409 ---- } // 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
*** 428,464 **** --- 420,452 ---- Klass* witness) { if (log == NULL) { return; } ciEnv* env = ciEnv::current(); ! ciBaseObject* ciargs[max_arg_count]; ! DepValue ciargs[max_arg_count]; assert(nargs <= max_arg_count, "oob"); for (int j = 0; j < nargs; j++) { if (args[j].is_oop()) { ! ciargs[j] = DepValue(env->get_object(args[j].oop_value())); } else { ! ciargs[j] = DepValue(env->get_metadata(args[j].metadata_value())); } } Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness); } void Dependencies::write_dependency_to(CompileLog* log, DepType dept, ! int nargs, ciBaseObject* args[], ! int nargs, DepValue args[], Klass* witness) { if (log == NULL) return; assert(nargs <= max_arg_count, "oob"); int argids[max_arg_count]; int ctxkj = dep_context_arg(dept); // -1 if no context arg int j; for (j = 0; j < nargs; j++) { if (args[j]->is_object()) { argids[j] = log->identify(args[j]->as_object()); } else { argids[j] = log->identify(args[j]->as_metadata()); } + argids[j] = args[j].log_identify(log); } if (witness != NULL) { log->begin_elem("dependency_failed"); } else { log->begin_elem("dependency");
*** 1180,1209 **** --- 1168,1197 ---- } return NULL; } ! bool Dependencies::is_concrete_klass(ciInstanceKlass* k) { ! if (k->is_abstract()) return false; ! bool Dependencies::is_concrete_klass(DepValue k) { ! if (k.is_abstract_klass()) return false; // We could also return false if k does not yet appear to be // instantiated, if the VM version supports this distinction also. //if (k->is_not_instantiated()) return false; return true; } ! bool Dependencies::is_concrete_method(ciMethod* m) { ! bool Dependencies::is_concrete_method(DepValue m) { // Statics are irrelevant to virtual call sites. ! if (m->is_static()) return false; ! if (m.is_static_method()) return false; // We could also return false if m does not yet appear to be // executed, if the VM version supports this distinction also. ! return !m->is_abstract(); ! return !m.is_abstract_method(); } ! bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) { ! return k->has_finalizable_subclass(); ! bool Dependencies::has_finalizable_subclass(DepValue k) { ! return k.instance_klass_has_finalizable_subclass(); } // Any use of the contents (bytecodes) of a method must be // marked by an "evol_method" dependency, if those contents

src/share/vm/code/dependencies.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File