< prev index next >
src/share/vm/code/dependencies.cpp
Print this page
@@ -24,31 +24,40 @@
#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,10 +127,24 @@
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,11 +393,13 @@
"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"
+ "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,11 +409,13 @@
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, // 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,10 +1556,26 @@
}
}
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,16 +1652,41 @@
// 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 >