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