< prev index next >
src/share/vm/code/dependencies.cpp
Print this page
*** 24,54 ****
#include "precompiled.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciMethod.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "code/dependencies.hpp"
#include "compiler/compileLog.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/copy.hpp"
-
#ifdef ASSERT
static bool must_be_in_vm() {
Thread* thread = Thread::current();
if (thread->is_Java_thread())
return ((JavaThread*)thread)->thread_state() == _thread_in_vm;
else
return true; //something like this: thread->is_VM_thread();
}
#endif //ASSERT
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);
--- 24,63 ----
#include "precompiled.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciKlass.hpp"
+ #include "ci/ciField.hpp"
#include "ci/ciMethod.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "code/dependencies.hpp"
#include "compiler/compileLog.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
+ #include "runtime/perfData.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/copy.hpp"
#ifdef ASSERT
static bool must_be_in_vm() {
Thread* thread = Thread::current();
if (thread->is_Java_thread())
return ((JavaThread*)thread)->thread_state() == _thread_in_vm;
else
return true; //something like this: thread->is_VM_thread();
}
#endif //ASSERT
+ // Globals
+
+ PerfCounter* Dependencies::_perf_dependency_checking_time = NULL;
+ PerfCounter* Dependencies::_perf_dependencies_checked_count = NULL;
+ PerfCounter* Dependencies::_perf_dependencies_invalidated = NULL;
+ PerfCounter* Dependencies::_perf_dependencies_total_count = NULL;
+ PerfCounter* Dependencies::_perf_dependencies_context_traversals = NULL;
+
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);
*** 118,127 ****
--- 127,150 ----
void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
assert_common_2(call_site_target_value, call_site, method_handle);
}
+ void Dependencies::assert_constant_field_value_klass(ciField* field, ciKlass* ctxk) {
+ // FIXME: how to record a field? no metadata associated; offset is int
+ assert_common_1(constant_field_value_klass, ctxk /*, field*/);
+ }
+
+ void Dependencies::assert_constant_field_value_instance(ciField* field, ciObject* obj) {
+ if (field->holder()->set_finals()) {
+ // FIXME: how to record a field? no metadata associated; offset is int
+ assert_common_2(constant_field_value_instance, field->holder(), /*field,*/ obj);
+ } else {
+ assert_constant_field_value_klass(field, field->holder());
+ }
+ }
+
// 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) {
*** 370,380 ****
"concrete_with_no_concrete_subtype",
"unique_concrete_method",
"abstract_with_exclusive_concrete_subtypes_2",
"exclusive_concrete_methods_2",
"no_finalizable_subclasses",
! "call_site_target_value"
};
int Dependencies::_dep_args[TYPE_LIMIT] = {
-1,// end_marker
1, // evol_method m
--- 393,405 ----
"concrete_with_no_concrete_subtype",
"unique_concrete_method",
"abstract_with_exclusive_concrete_subtypes_2",
"exclusive_concrete_methods_2",
"no_finalizable_subclasses",
! "call_site_target_value",
! "constant_field_value_instance",
! "constant_field_value_klass"
};
int Dependencies::_dep_args[TYPE_LIMIT] = {
-1,// end_marker
1, // evol_method m
*** 384,394 ****
1, // concrete_with_no_concrete_subtype ctxk
2, // unique_concrete_method ctxk, m
3, // unique_concrete_subtypes_2 ctxk, k1, k2
3, // unique_concrete_methods_2 ctxk, m1, m2
1, // no_finalizable_subclasses ctxk
! 2 // call_site_target_value call_site, method_handle
};
const char* Dependencies::dep_name(Dependencies::DepType dept) {
if (!dept_in_mask(dept, all_types)) return "?bad-dep?";
return _dep_name[dept];
--- 409,421 ----
1, // concrete_with_no_concrete_subtype ctxk
2, // unique_concrete_method ctxk, m
3, // unique_concrete_subtypes_2 ctxk, k1, k2
3, // unique_concrete_methods_2 ctxk, m1, m2
1, // no_finalizable_subclasses ctxk
! 2, // call_site_target_value call_site, method_handle
! 2, // constant_field_value_instance ctxk oop
! 1 // constant_field_value_klass ctxk
};
const char* Dependencies::dep_name(Dependencies::DepType dept) {
if (!dept_in_mask(dept, all_types)) return "?bad-dep?";
return _dep_name[dept];
*** 1529,1538 ****
--- 1556,1581 ----
}
}
return NULL; // assertion still valid
}
+ void Dependencies::invalidate_dependent_nmethods(instanceKlassHandle ctxk, DepChange& changes, TRAPS) {
+ MutexLocker mu(Compile_lock, THREAD);
+
+ int marked = 0;
+ {
+ MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ marked = ctxk->mark_dependent_nmethods(changes);
+ }
+ if (marked > 0) {
+ ctxk->set_finals(true);
+ // At least one nmethod has been marked for deoptimization
+ VM_Deoptimize op;
+ VMThread::execute(&op);
+ }
+ }
+
void Dependencies::DepStream::trace_and_log_witness(Klass* witness) {
if (witness != NULL) {
if (TraceDependencies) {
print_dependency(witness, /*verbose=*/ true);
}
*** 1609,1624 ****
--- 1652,1692 ----
// Handle CallSite dependency
if (changes.is_call_site_change())
return check_call_site_dependency(changes.as_call_site_change());
+ if (changes.is_constant_field_change()) {
+ Handle holder = changes.as_constant_field_change()->holder();
+ int offset = changes.as_constant_field_change()->offset();
+ int dep_offset = -1; // TODO: store offset in dependency
+ switch (type()) {
+ case constant_field_value_instance:
+ if (holder.is_null()) return context_type(); // all oops
+ if (holder() == argument_oop(1)) {
+ if (offset == -1) return context_type(); // all fields
+ if (offset == dep_offset) return context_type(); // same field
+ }
+ break;
+ case constant_field_value_klass:
+ if (offset == -1) return context_type(); // all fields
+ if (offset == dep_offset) return context_type(); // same field
+ break;
+ }
+ }
+
// irrelevant dependency; skip it
return NULL;
}
void DepChange::print() {
+ if (is_klass_change())
+ tty->print_cr("klass_change");
+ if (is_call_site_change())
+ tty->print_cr("call_site_change");
+ if (is_constant_field_change())
+ tty->print_cr("constant_field_change: offset=%d %s", as_constant_field_change()->offset(), as_constant_field_change()->holder()->print_string());
int nsup = 0, nint = 0;
for (ContextStream str(*this); str.next(); ) {
Klass* k = str.klass();
switch (str.change_type()) {
case Change_new_type:
< prev index next >