< 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 >