nmethod.cpp revision 1765
553N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A#
include "incls/_precompiled.incl" 0N/A// Only bother with this argument setup if dtrace is available 0N/A const char*,
int,
const char*,
int,
const char*,
int,
void*,
size_t);
0N/A char*,
int,
char*,
int,
char*,
int);
#
else // ndef DTRACE_ENABLED//--------------------------------------------------------------------------------- // They are printed under various flags, including: // PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation. // (In the latter two cases, they like other stats are printed to the log only.) // These variables are put into one block to reduce relocations // and make it simpler to print from the debugger. tty->
print_cr(
"PcDesc Statistics: %d queries, %.2f comparisons per query",
tty->
print_cr(
" caches=%d queries=%d/%d, hits=%d+%d, tests=%d+%d, adds=%d",
//--------------------------------------------------------------------------------- // The _unwind_handler is a special marker address, which says that // for given exception oop and address, the frame should be removed // as the tuple cannot be caught in the nmethod for (
int i=0; i<
count(); i++) {
// private method for handling exception cache // These methods are private, and used to manipulate the exception cache //----------------------------------------------------------------------------- // Helper used by both find_pc_desc methods. // reset the cache by filling it with benign (non-null) values // In order to prevent race conditions do not load cache elements // repeatedly, but use a local copy: // Step one: Check the most recently returned value. if (
res ==
NULL)
return NULL;
// native method; no PcDescs at all // Step two: Check the LRU cache. if (
res->
pc_offset() < 0)
break;
// optimization: skip empty cache // Update the LRU cache by shifting pc_desc forward: // Note: Do not update _last_pc_desc. It fronts for the LRU cache. // adjust pcs_size so that it is a multiple of both oopSize and // sizeof(PcDesc) (assumes that if sizeof(PcDesc) is not a multiple // of oopSize, then 2*sizeof(PcDesc) is) //----------------------------------------------------------------------------- // find the previous and next entry of ec // public method for accessing the exception cache // These are the public access methods. // We never grab a lock to read the exception cache, so we may // have false negatives. This is okay, as it can only happen during // the first few exception lookups for a given nmethod. // There are potential race conditions during exception cache updates, so we // must own the ExceptionCache_lock before doing ANY modifications. Because // we don't lock during reads, it is possible to have several threads attempt // to update the cache with the same data. We need to check for already inserted // copies of the current data before adding it. //-------------end of code for ExceptionCache-------------- // Fill in default values for various flag fields #
endif // def HAVE_DTRACE_H#
endif // def HAVE_DTRACE_H // To make dependency checking during class loading fast, record // the nmethod dependencies in the classes it is dependent on. // This allows the dependency checking code to simply walk the // class hierarchy above the loaded class, checking only nmethods // which are dependent on those classes. The slow way is to // check every nmethod for dependencies which makes it linear in // the number of methods compiled. For applications with a lot // classes the slow way is too slow. if (
klass ==
NULL)
continue;
// ignore things like evol_method // record this nmethod as dependent on this klass // We have no exception handler or deopt handler make the // values something that will never match a pc like the nmethod vtable entry // This output goes directly to the tty, not the compiler log. // To enable tools to match it up with the compilation activity, // be sure to tag this tty output with the compile ID. // print the header part first // then print the requested information // We have no exception handler or deopt handler make the // values something that will never match a pc like the nmethod vtable entry // This output goes directly to the tty, not the compiler log. // To enable tools to match it up with the compilation activity, // be sure to tag this tty output with the compile ID. // print the header part first // then print the requested information #
endif // def HAVE_DTRACE_H // Always leave some room in the CodeCache for I2C/C2I adapters // Exception handler and deopt handler are in the stub section // Copy contents of ScopeDescRecorder to nmethod // Copy contents of ExceptionHandlerTable to nmethod // we use the information of entry points to find out if a method is " entry points must be same for static methods and vice versa");
// Note: Do not verify in here as the CodeCache_lock is // taken which would conflict with the CompiledIC_lock // which taken during the verification of call sites. // (was bug - gri 10/25/99) // Print a short set of xml attributes to identify this nmethod. The // output should be embedded in some other element. // print compilation number // print method attributes // print method name string if given // otherwise as the method to print itself // Print out more verbose output usually for a newly created nmethod. method(),
/*is_blocking*/false,
// print the header part first // then print the requested information // Promote one word from an assembly-time handle to a live embedded oop. // As a special case, IC oops are initialized to 1 or -1. //assert(oops_size() == 0, "do this handshake just once, please"); // Now we can fix up all the oops in the code. We need to do this // in the code because the assembler uses jobjects as placeholders. // The code and relocations have already been initialized by the // CodeBlob constructor, so it is valid even at this early point to // iterate over relocations and patch the code. // re-patch all oop-bearing instructions, just in case some oops moved // Refresh the oop-related bits of this instruction. // There must not be any interfering patches or breakpoints. // If the method is not entrant or zombie then a JMP is plastered over the // first few bytes. If an oop in the old code was there, that oop // should not get GC'd. Skip the first few bytes of oops on // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. // This means that the low_boundary is going to be a little too high. // This shouldn't matter, since oops of non-entrant methods are never used. // In fact, why are we bothering to look at oops in a non-entrant method?? // Find all calls in an nmethod, and clear the ones that points to zombie methods // Ok, to lookup references to zombies here // Clean inline caches pointing to both zombie and not_entrant methods // Clean inline caches pointing to both zombie and not_entrant methods // This is a private interface with the sweeper. // Set the traversal mark to ensure that the sweeper does 2 // cleaning passes before moving to zombie. // Tell if a non-entrant method can be converted to a zombie (i.e., there is no activations on the stack) // Since the nmethod sweeper only does partial sweep the sweeper's traversal // count can be greater than the stack traversal count before it hits the // nmethod for the second time. // Could be gated by ProfileTraps, but do not bother... // Since this nmethod is being unloaded, make sure that dependencies // recorded in instanceKlasses get flushed and pass non-NULL closure to // indicate that this work is being done during a GC. // A non-NULL is_alive closure indicates that this is being called during GC. // Break cycle between nmethod & method // Unlink the osr method, so we do not look this up again // If _method is already NULL the methodOop is about to be unloaded, // so we don't have to break the cycle. Note that it is possible to // have the methodOop live here, in case we unload the nmethod because // it is pointing to some oop (other than the methodOop) being unloaded. // OSR methods point to the methodOop, but the methodOop does not _method =
NULL;
// Clear the method of this dead nmethod // Make the class unloaded - i.e., change state and notify sweeper // Transitioning directly from live to unloaded -- so // we need to force a cache clean-up; remember this // The methodOop is gone at this point //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods // Remove from list of active nmethods // Common functionality for both make_not_entrant and make_zombie // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. // If the method is already zombie there is nothing to do // invalidate osr nmethod before acquiring the patching lock since // they both acquire leaf locks and we don't want a deadlock. // This logic is equivalent to the logic below for patching the // verified entry point of regular methods. // this effectively makes the osr nmethod not entrant // Enter critical section. Does not block for safepoint. // another thread already performed this transition so nothing // to do, but return false to indicate this. // The caller can be calling the method statically or through an inline // It's a true state change, so mark the method as decompiled. // Do it only for transition from alive. // Log the transition once // Remove nmethod from method. // We need to check if both the _code and _from_compiled_code_entry_point // refer to this nmethod because there is a race in setting these two fields // in methodOop as seen in bugid 4947125. // If the vep() points to the zombie nmethod, the memory for the nmethod // could be flushed and the compiler and vtable stubs could still call }
// leave critical region under Patching_lock // When the nmethod becomes zombie it is no longer alive so the // dependencies must be flushed. nmethods in the not_entrant // state will be flushed later when the transition to zombie // happens or they get unloaded. // Flushing dependecies must be done before any possible // safepoint can sneak in, otherwise the oops used by the // dependency logic could have become stale. // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event // and it hasn't already been reported for this nmethod then report it now. // (the event may have been reported earilier if the GC marked it for unloading). // It's no longer safe to access the oops section since zombie // nmethods aren't scanned for GC. // Make sweeper aware that there is a zombie method that needs to be removed // Note that there are no valid oops in the nmethod anymore. // completely deallocate this method // We need to deallocate any ExceptionCache data. // Note that we do not need to grab the nmethod lock for this, it // better be thread safe if we're disposing of it! // Notify all classes this nmethod is dependent on that it is no // longer dependent. This should only be called in two situations. // First, when a nmethod transitions to a zombie all dependents need // to be clear. Since zombification happens at a safepoint there's no // synchronization issues. The second place is a little more tricky. // During phase 1 of mark sweep class unloading may happen and as a // result some nmethods may get unloaded. In this case the flushing // of dependencies must happen during phase 1 since after GC any // dependencies in the unloaded nmethod won't be updated, so // traversing the dependency information in unsafe. In that case this // function is called with a non-NULL argument and this function only // notifies instanceKlasses that are reachable "is_alive is non-NULL if and only if we are called during GC");
if (
klass ==
NULL)
continue;
// ignore things like evol_method // During GC the is_alive closure is non-NULL, and is used to // determine liveness of dependees that need to be updated. // If this oop is not live, the nmethod can be unloaded. // The oop should be kept alive // If ScavengeRootsInCode is true, an nmethod might be unloaded // simply because one of its constant oops has gone dead. // No actual classes need to be unloaded in order for this to occur. // ------------------------------------------------------------------ // post_compiled_method_load_event // new method for install_code() path // Transfer information from compilation to jvmti // Cache the jmethod_id since it can no longer be looked up once the // method itself has been marked for unloading. // During unloading we transition to unloaded and then to zombie // and the unloading is reported during the first transition. // If a JVMTI agent has enabled the CompiledMethodUnload event then // post the event. Sometime later this nmethod will be made a zombie // by the sweeper but the methodOop will not be valid at that point. // If the _jmethod_id is null then no load event was ever requested // so don't bother posting the unload. The main reason for this is // that the jmethodID is a weak reference to the methodOop so if // it's being unloaded there's no way to look it up since the weak // ref will have been cleared. // The JVMTI CompiledMethodUnload event can be enabled or disabled at // any time. As the nmethod is being unloaded now we mark it has // having the unload event reported - this will ensure that we don't // attempt to report the event in the unlikely scenario where the // event is enabled at the time the nmethod is made a zombie. // GC to unload an nmethod if it contains otherwise unreachable // Make sure the oop's ready to receive visitors "should not call follow on zombie or unloaded nmethod");
// If the method is not entrant then a JMP is plastered over the // first few bytes. If an oop in the old code was there, that oop // should not get GC'd. Skip the first few bytes of oops on // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. // The RedefineClasses() API can cause the class unloading invariant // Also, leave a debugging breadcrumb in local flag. // This set of the unloading_occurred flag is done before the // call to post_compiled_method_unload() so that the unloading // of this nmethod is reported. // If class unloading occurred we first iterate over all inline caches and // clear ICs where the cached oop is referring to an unloaded klass or method. // The remaining live cached oops will be traversed in the relocInfo::oop_type // The only exception is compiledICHolder oops which may // yet be marked below. (We check this further below). "cached oop in IC should be cleared");
// In this loop, we must only traverse those oops directly embedded in // the code. Other oops (oop_index>0) are seen as part of scopes_oops. "oop must be found in exactly one place");
// This nmethod was not unloaded; check below that all CompiledICs "Found unmarked ic_oop in reachable nmethod");
// This method is called twice during GC -- once while // tracing the "active" nmethods on thread stacks during // the (strong) marking phase, and then again when walking // the code cache contents during the weak roots processing // phase. The two uses are distinguished by means of the // 'do_strong_roots_only' flag, which is true in the first // case. We want to walk the weak roots in the nmethod // only in the second case. The weak roots in the nmethod // are the oops in the ExceptionCache and the InlineCache // make sure the oops ready to receive visitors "should not call follow on zombie or unloaded nmethod");
// If the method is not entrant or zombie then a JMP is plastered over the // first few bytes. If an oop in the old code was there, that oop // should not get GC'd. Skip the first few bytes of oops on // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. // weak roots processing phase -- update ExceptionCache oops }
// Else strong roots phase -- skip oops in ExceptionCache // In this loop, we must only follow those oops directly embedded in // the code. Other oops (oop_index>0) are seen as part of scopes_oops. "oop must be found in exactly one place");
// This includes oop constants not inlined in the code stream. // An nmethod is "marked" if its _mark_link is set non-null. // Even if it is the end of the linked list, it will have a non-null link value, // as long as it is on the list. // This code must be MP safe, because it is used from parallel GC passes. // Claim this nmethod for this thread to mark. // Atomically append this nmethod (now claimed) to the head of the list: // Mark was clear when we first saw this guy. // On fall through, another racing thread marked this nmethod before we did. // We use cmpxchg_ptr instead of regular assignment here because the user // may fork a bunch of threads, and we need them all to see the same state. // Method that knows how to preserve outgoing arguments at call. This method must be // called with a frame corresponding to a Java invoke assert(
count >=
2,
"must be sentinel values, at least");
// must be sorted and unique; we do a binary search in find_pc_desc() "must start with a sentinel");
for (
int i =
1; i <
count; i++) {
"must end with a sentinel");
// Search for MethodHandle invokes and tag the nmethod. for (
int i = 0; i <
count; i++) {
// Adjust the final sentinel downward. // Fill any rounding gaps with copies of the last record. // The following assert could fail if sizeof(PcDesc) is not // an integral multiple of oopSize (the rounding term). // If it fails, change the logic to always allocate a multiple // of sizeof(PcDesc), and fill unused words with copies of *last_pc. lower +=
1;
// exclude initial sentinel // Finds a PcDesc with real-pc equal to "pc" return NULL;
// PC is wildly out of range // Check the PcDesc cache if it contains the desired PcDesc // (This as an almost 100% hit rate.) // Fallback algorithm: quasi-linear search for the PcDesc // Find the last pc_offset less than the given offset. // The successor must be the required match, if there is a match at all. // (Use a fixed radix to avoid expensive affine pointer arithmetic.) upper -=
1;
// exclude final sentinel /* invariant on lower..upper during the following search: */ \
// Use the last successful return as a split point. // Take giant steps at first (4096, then 256, then 16, then 1) // Sneak up on the value with a linear search of length ~16. // wholesale check of all dependencies return found_check;
// tell caller if we found anything // 1) a new class dependee has been added // 2) dependee and all its super classes have been marked // Evaluate only relevant dependencies. // RC_TRACE macro has an embedded ResourceMark (
"Found evol dependency of nmethod %s.%s(%s) compile_id=%d on method %s.%s(%s)",
// Called from mark_for_deoptimization, when dependee is invalidated. // a zombie may never be patched // Exception happened outside inline-cache check code => we are inside // an active nmethod => use cpc to determine a return address // Let the normal error handling report the exception // make sure you didn't forget to adjust the filler fields //------------------------------------------------------------------------------------------- // QQQ might we make this work from a frame?? // ----------------------------------------------------------------------------- // nmethod::get_deopt_original_pc // Return the original PC for the given PC if: // (a) the given PC belongs to a nmethod and // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- bool ok() {
return _ok; }
// Hmm. OSR methods can be deopted but not marked as zombie or not_entrant // Make sure all the entry points are correctly aligned for patching. // This code does not work in release mode since // owns_lock only is available in debug mode. if( !
method() )
return;
// Runtime stubs have no scope // iterate through all interrupt point // and verify the debug information is valid. //verify_interrupt_point(iter.addr()); // Right now there is no way to find out which entries support // an interrupt point. It would be nice if we had this // information in a table. // ----------------------------------------------------------------------------- bool ok() {
return _ok; }
// Actually look inside, to verify the claim that it's clean. fatal(
"found an unadvertised bad non-perm oop in the code cache");
// Find the first pc desc for all scopes in the code and print it. ResourceMark m;
// in case methods get printed via the debugger // Return a the last scope in (begin..end] const char*
spname =
"sp";
// make arch-specific? // First, find an oopmap in (begin, end]. // We use the odd half-closed interval so that oop maps and scope descs // which are tied to the byte after a call are printed with the call itself. // Print any debug info present at this pc. st->
print(
";*synchronization entry");
// Print relocation information