--- old/src/share/vm/code/nmethod.cpp 2014-04-14 10:01:23.827015791 +0200 +++ new/src/share/vm/code/nmethod.cpp 2014-04-14 10:01:22.899015756 +0200 @@ -486,7 +486,7 @@ CodeOffsets offsets; offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); - nm = new (native_nmethod_size) nmethod(method(), native_nmethod_size, + nm = new (native_nmethod_size, CompLevel_none) nmethod(method(), native_nmethod_size, compile_id, &offsets, code_buffer, frame_size, basic_lock_owner_sp_offset, @@ -524,7 +524,7 @@ offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); - nm = new (nmethod_size) nmethod(method(), nmethod_size, + nm = new (nmethod_size, CompLevel_none) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size); NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); @@ -572,7 +572,7 @@ + round_to(nul_chk_table->size_in_bytes(), oopSize) + round_to(debug_info->data_size() , oopSize); - nm = new (nmethod_size) + nm = new (nmethod_size, comp_level) nmethod(method(), nmethod_size, compile_id, entry_bci, offsets, orig_pc_offset, debug_info, dependencies, code_buffer, frame_size, oop_maps, @@ -781,9 +781,10 @@ } #endif // def HAVE_DTRACE_H -void* nmethod::operator new(size_t size, int nmethod_size) throw() { - // Not critical, may return null if there is too little continuous memory - return CodeCache::allocate(nmethod_size); +void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw () { + // Nmethods are allocated on separate heaps and therefore do not share memory with critical CodeBlobs. + // We nevertheless define the allocation as critical to make sure all heap memory is used. + return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level), true); } nmethod::nmethod( @@ -1416,7 +1417,7 @@ Events::log(JavaThread::current(), "flushing nmethod " INTPTR_FORMAT, this); if (PrintMethodFlushing) { tty->print_cr("*flushing nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT "/Free CodeCache:" SIZE_FORMAT "Kb", - _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity()/1024); + _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity(CodeCache::get_code_blob_type(_comp_level))/1024); } // We need to deallocate any ExceptionCache data. @@ -1440,10 +1441,9 @@ ((CodeBlob*)(this))->flush(); - CodeCache::free(this); + CodeCache::free(this, CodeCache::get_code_blob_type(_comp_level)); } - // // Notify all classes this nmethod is dependent on that it is no // longer dependent. This should only be called in two situations. @@ -2132,41 +2132,46 @@ void nmethod::check_all_dependencies(DepChange& changes) { - // Checked dependencies are allocated into this ResourceMark - ResourceMark rm; + // Checked dependencies are allocated into this ResourceMark + ResourceMark rm; - // Turn off dependency tracing while actually testing dependencies. - NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) ); + // Turn off dependency tracing while actually testing dependencies. + NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) ); typedef ResourceHashtable DepTable; DepTable* table = new DepTable(); - // Iterate over live nmethods and check dependencies of all nmethods that are not - // marked for deoptimization. A particular dependency is only checked once. - for(nmethod* nm = CodeCache::alive_nmethod(CodeCache::first()); nm != NULL; nm = CodeCache::alive_nmethod(CodeCache::next(nm))) { - if (!nm->is_marked_for_deoptimization()) { - for (Dependencies::DepStream deps(nm); deps.next(); ) { - // Construct abstraction of a dependency. - DependencySignature* current_sig = new DependencySignature(deps); - - // Determine if dependency is already checked. table->put(...) returns - // 'true' if the dependency is added (i.e., was not in the hashtable). - if (table->put(*current_sig, 1)) { - if (deps.check_dependency() != NULL) { - // Dependency checking failed. Print out information about the failed - // dependency and finally fail with an assert. We can fail here, since - // dependency checking is never done in a product build. - changes.print(); - nm->print(); - nm->print_dependencies(); - assert(false, "Should have been marked for deoptimization"); - } - } - } - } - } + // Iterate over live nmethods and check dependencies of all nmethods that are not + // marked for deoptimization. A particular dependency is only checked once. + for (int code_blob_type = CodeBlobType::MethodNonProfiled; code_blob_type <= CodeBlobType::MethodProfiled; ++code_blob_type) { + // Only notify for live nmethods + nmethod* nm = (nmethod*) CodeCache::first_alive_blob(code_blob_type); + while (nm != NULL) { + if (!nm->is_marked_for_deoptimization()) { + for (Dependencies::DepStream deps(nm); deps.next(); ) { + // Construct abstraction of a dependency. + DependencySignature* current_sig = new DependencySignature(deps); + + // Determine if dependency is already checked. table->put(...) returns + // 'true' if the dependency is added (i.e., was not in the hashtable). + if (table->put(*current_sig, 1)) { + if (deps.check_dependency() != NULL) { + // Dependency checking failed. Print out information about the failed + // dependency and finally fail with an assert. We can fail here, since + // dependency checking is never done in a product build. + changes.print(); + nm->print(); + nm->print_dependencies(); + assert(false, "Should have been marked for deoptimization"); + } + } + } + } + nm = (nmethod*) CodeCache::next_alive_blob(nm, code_blob_type); + } + } } bool nmethod::check_dependency_on(DepChange& changes) { @@ -2359,7 +2364,7 @@ ResourceMark rm; - if (!CodeCache::contains(this)) { + if (!CodeCache::contains_nmethod(this)) { fatal(err_msg("nmethod at " INTPTR_FORMAT " not in zone", this)); }