parse1.cpp revision 1879
1636N/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. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A// Static array so we can figure out which bytecodes stop us from compiling 0N/A// and eventually should be encapsulated in a proper class (gri 8/18/98). 0N/A//------------------------------print_statistics------------------------------- //------------------------------ON STACK REPLACEMENT--------------------------- // Construct a node which can be used to get incoming state for // Very similar to LoadNode::make, except we handle un-aligned longs and // doubles on Sparc. Intel can handle them just fine directly. switch(
bt ) {
// Signature is flattened // Since arguments are in reverse order, the argument address 'adr' // refers to the back half of the long/double. Recompute adr. // Helper routine to prevent the interpreter from handing // unexpected typestate to an OSR method. // The Node l is a value newly dug out of the interpreter frame. // The type is the type predicted by ciTypeFlow. Note that it is // not a general type, but can only come from Type::get_typeflow_type. // The safepoint is a map which will feed an uncommon trap. // TypeFlow may assert null-ness if a type appears unloaded. // Value must be null, not a real oop. // Typeflow can also cut off paths from the CFG, based on // types which appear unloaded, or call sites which appear unlinked. // When paths are cut off, values at later merge points can rise // toward more specific classes. Make sure these specific classes // TypeFlow asserted a specific object type. Value must have that type. // Helper routine which sets up elements of the initial parser map when // performing a parse for on stack replacement. Add values into map. // The only parameter contains the address of a interpreter arguments. // Mismatch between method and jvms can occur since map briefly held // an OSR entry state (which takes up one RawPtr word). // Set initial stack depth. // Check bailouts. We currently do not perform on stack replacement // of loops in catch blocks or loops which branch with a non-empty stack. // Do not OSR inside finally clauses: // Commute monitors from interpreter frame to compiler frame. // Make a BoxLockNode for the monitor. // Displaced headers and locked objects are interleaved in the // temp OSR buffer. We only copy the locked objects out here. // Fetch the locked object from the OSR temp buffer and copy to our fastlock node. // Try and copy the displaced header to the BoxNode // Build a bogus FastLockNode (no code will be generated) and push the // monitor into our debug info. // If the lock is our method synchronization lock, tuck it away in // _sync_lock for return and rethrow exit paths. // Use the raw liveness computation to make sure that unexpected // values don't propagate into the OSR frame. // Degenerate or breakpointed method. // Extract the needed locals from the interpreter frame. // find all the locals that the interpreter thinks contain live oops // 6403625: Verify that the interpreter oopMap thinks that the oop is live // else we might load a stale oop if the MethodLiveness disagrees with the // result of the interpreter. If the interpreter says it is dead we agree // by making the value go to top. // and ignore it for the loads // Filter out TOP, HALF, and BOTTOM. (Cf. ensure_phi.) // If the type falls to bottom, then this must be a local that // is mixing ints and oops or some such. Forcing it to top // Construct code to access the appropriate local. // Ptr types are mixed together with T_ADDRESS but NULL is // really for T_OBJECT types so correct it. // Extract the needed stack entries from the interpreter frame. // Currently the compiler bails out when attempting to on stack replace // at a bci with a non-empty stack. We should not reach here. // Now that the interpreter state is loaded, make sure it will match // at execution time what the compiler is expecting now: if (l->
is_top())
continue;
// nothing here // skip type check for dead oops // In our current system it's illegal for jsr addresses to be // live into an OSR entry point because the compiler performs // inlining of jsrs. ciTypeFlow has a bailout that detect this // case and aborts the compile if addresses are live into an OSR // entry point. Because of that we can assume that any address // locals at the OSR entry point are dead. Method liveness // isn't precise enought to figure out that they are dead in all // cases so simply skip checking address locals all // together. Any type check is guaranteed to fail since the // interpreter type is the result of a load which might have any // value and the expected type is a constant. if (l->
is_top())
continue;
// nothing here // Build an uncommon trap here, if any inputs can be unexpected. // The unexpected type happens because a new edge is active // in the CFG, which typeflow had previously ignored. // E.g., Object x = coldAtFirst() && notReached()? "str": new Integer(123). // This x will be typed as Integer if notReached is not yet linked. //------------------------------Parse------------------------------------------ // Main parser constructor. // Make sure I have an inline tree, so I can print messages about it. // Accumulate deoptimization counts. // (The range_check and store_check counts are checked elsewhere.) // Saturate the add if it overflows. log->
elem(
"observe trap='%s' count='%d' total='%d'",
// Accumulate total sum of decompilations, also. log->
elem(
"observe that='has_exception_handlers'");
// Always register dependence if JVMTI is enabled, because // either breakpoint setting or hotswapping of methods may // Do some special top-level things. _tf = C->
tf();
// the OSR entry type is different "Must invalidate if TypeFuncs differ");
// add method size here to guarantee that inlined methods are added too // Import the results of the ciTypeFlow. // Merge point for all normal exits // Setup the initial JVM state map. // Check for bailouts during map initialization // Collect debug info for inlined calls unless -XX:-DebugInlinedCalls. // Check for bailouts during method entry. entry_map =
map();
// capture any changes performed by method setup code // We begin parsing as if we have just encountered a jump to the // Parse all the basic blocks. // Check for bailouts during conversion to graph // Fix up all exiting control flow. if (
log)
log->
done(
"parse nodes='%d' memory='%d'",
//---------------------------do_all_blocks------------------------------------- // Walk over all blocks in Reverse Post-Order. // Dead block, no state reaches this block // Prepare to parse this block. // Not all preds have been parsed. We must build phis everywhere. // (Note that dead locals do not get phis built, ever.) // Leave behind an undisturbed copy of the map, for future merges. // In the absence of irreducible loops, the Region and Phis // associated with a merge that doesn't involve a backedge can // be simplified now since the RPO parsing order guarantees // that any path which was supposed to reach here has already // been parsed or must be dead. // with irreducible loops multiple passes might be necessary to parse everything // Make sure there are no half-processed blocks remaining. // Every remaining unprocessed block is dead and may be ignored now. //-------------------------------build_exits---------------------------------- // Build normal and exceptional exit merge points. // make a clone of caller to prevent sharing of side-effects // Note: iophi and memphi are not transformed until do_exits. // Add a return value to the exit state. (Do not push it yet.) // Don't "bind" an unloaded return klass to the ret_phi. If the klass // becomes loaded during the subsequent parsing, the loaded and unloaded // types will not join when we transform and push in do_exits(). // Note: ret_phi is not yet pushed, until do_exits. //----------------------------build_start_state------------------------------- // Construct a state which contains only the incoming arguments from an // unknown caller. The method & bci will be NULL & InvocationEntryBci. // Record all these guys for later GVN. //-----------------------------make_node_notes--------------------------------- //--------------------------return_values-------------------------------------- // Add zero or 1 return values // Note: The second dummy edge is not needed by a ReturnNode. //------------------------rethrow_exceptions----------------------------------- // Bind all exception states in the list into a single RethrowNode. // Load my combined exception state into the kit, with all phis transformed: // like a return but with exception input //---------------------------do_exceptions------------------------------------- // Process exceptions arising from the current bytecode. // Send caught exceptions to the proper handler within this method. // Unhandled exceptions feed into _exit. // Pop them all off and throw them away. // Common case: Transfer control outward. // Doing it this early allows the exceptions to common up // even between adjacent method calls. // Have to look at the exception first. // We now return to our regularly scheduled program: //---------------------------throw_to_exit------------------------------------- // Merge the given map into an exception exit from this method. // The exception exit will handle any unlocking of receiver. // The ex_oop must be saved within the ex_map, unlike merge_exception. // Pop the JVMS to (a copy of) the caller. // Copy out the standard machine state: // Finally, collect the new exception state in my exits: //------------------------------do_exits--------------------------------------- // Now peephole on the return bits // This method (which must be a constructor by the rules of Java) // wrote a final. The effects of all initializations must be // committed to memory before any code after the constructor // publishes the reference to the newly constructor object. // Rather than wait for the publication, we simply block the // writes here. Rather than put a barrier on only those writes // which are required to complete, we force all writes to complete. // "All bets are off" unless the first publication occurs after a // normal return from the constructor. We do not attempt to detect // such unusual early publications. But no barrier is needed on // exceptional returns, since they cannot publish normally. tty->
print_cr(
" writes finals and needs a memory barrier");
// transform each slice of the original memphi: // Note: Logic for creating and optimizing the ReturnNode is in Compile. // Unlock along the exceptional paths. // This is done late so that we can common up equivalent exceptions // (e.g., null checks) arising from multiple points within this method. // See GraphKit::add_exception_state, which performs the commoning. // record exit from a method if compiled while Dtrace is turned on. // First move the exception list out of _exits: // Now re-collect the exceptions into _exits: // Force the exiting JVM state to have this method at InvocationEntryBci. // The exiting JVM state is otherwise a copy of the calling JVMS. // Add on the synchronized-method box/object combo // Done with exception-path processing. // Pop the last vestige of this method: // Capture very early exceptions (receiver null checks) from caller JVMS //-----------------------------create_entry_map------------------------------- // Initialize our parser map to contain the types at method entry. // For OSR, the map contains a single RawPtr parameter. // Initial monitor locking for sync. methods is performed by do_method_entry. // Check for really stupid bail-out cases. // If this is an inlined method, we may have to do a receiver null check. // Create an initial safepoint to hold JVM state during parsing // Pass thru the predefined input parameters. // Insert the memory aliasing node // Now add the locals which are initially bound to arguments: // Clear out the rest of the map (locals and stack) //-----------------------------do_method_entry-------------------------------- // Emit any code needed in the pseudo-block before BCI zero. // The main thing to do is lock the receiver of a synchronized method. set_sp(0);
// Java Stack Pointer // If the method is synchronized, we need to construct a lock node, attach // it to the Start node, and pin it there. // Insert a FastLockNode right after the Start which takes as arguments // the current thread pointer, the "this" pointer & the address of the // stack slot pair used for the lock. The "this" pointer is a projection // off the start node, but the locking spot has to be constructed by // creating a ConLNode of 0, and boxing it with a BoxLockNode. The BoxLockNode // becomes the second argument to the FastLockNode call. The // FastLockNode becomes the new control parent to pin it to the start. }
else {
// Else pass the "this" pointer, // Clear out dead values from the debug info. // Build the FastLockNode //------------------------------init_blocks------------------------------------ // Initialize our parser map to contain the types/monitors at method entry. // Initialize the structs. // Collect predecessor and successor information. //-------------------------------init_node------------------------------------- // entry point has additional predecessor //-------------------------------init_graph------------------------------------ // Create the successor list for this parser block. for (
int i = 0; i <
ns+
ne; i++) {
// Accumulate pred info for the other block, too. // A block's successors must be distinguishable by BCI. // That is, no bytecode is allowed to branch to two different // clones of the same code location. for (
int j = 0; j < i; j++) {
// Note: We never call next_path_num along exception paths, so they // never get processed as "ready". Also, the input phis of exception // handlers get specially processed, so that //---------------------------successor_for_bci--------------------------------- // We can actually reach here if ciTypeFlow traps out a block // due to an unloaded class, and concurrently with compilation the // class is then loaded, so that a later phase of the parser is // able to see more of the bytecode CFG. Or, the flow pass and // the parser can have a minor difference of opinion about executability // of bytecodes. For example, "obj.field = null" is executable even // if the field's type is an unloaded class; the flow pass used to // make a trap for such code. //-----------------------------stack_type_at----------------------------------- //-----------------------------local_type_at----------------------------------- // Make dead locals fall to bottom. // This bitmap can be zero length if we saw a breakpoint. // In such cases, pretend they are all live. //----------------------------name_for_bc-------------------------------------- // helper method for BytecodeParseHistogram //----------------------------BytecodeParseHistogram------------------------------------ //----------------------------current_count------------------------------------ //----------------------------initialized-------------------------------------- //----------------------------reset-------------------------------------------- //----------------------------set_initial_state-------------------------------- // Record info when starting to parse one bytecode //----------------------------record_change-------------------------------- // Record results of parsing one bytecode //----------------------------print-------------------------------------------- tty->
cr();
//0123456789012345678901234567890123456789012345678901234567890123456789 if(
total == 0 ) {
return; }
tty->
print_cr(
"absolute: count of compiled bytecodes of this type");
tty->
print_cr(
"relative: percentage contribution to compiled nodes");
tty->
print_cr(
"nodes : Average number of nodes constructed per bytecode");
tty->
print_cr(
"rnodes : Significance towards total nodes constructed, (nodes*relative)");
tty->
print_cr(
"transforms: Average amount of tranform progress per bytecode compiled");
tty->
print_cr(
"values : Average number of node values improved per bytecode");
tty->
print_cr(
" absolute relative nodes rnodes transforms values name");
tty->
print_cr(
"----------------------------------------------------------------------");
tty->
print_cr(
"----------------------------------------------------------------------");
tty->
print_cr(
"----------------------------------------------------------------------");
//----------------------------load_state_from---------------------------------- // load the block's JVM state: //-----------------------------record_state------------------------------------ //------------------------------do_one_block----------------------------------- tty->
print(
"Parsing block #%d at bci [%d,%d), successors: ",
for (
int i = 0; i <
nt; i++) {
// Set iterator to start of block. // Learn the current bci from the iterator: // insert a predicate if it falls through to a loop head block // Do not walk into the next block until directed by do_all_blocks. // Output an optional context marker, to help place actions // that occur during parsing of this BC. If there is no log // output until the next context string, this context string // will be silently ignored. // We must respect the flow pass's traps, because it will refuse // to produce successors for trapping blocks. // Fall into next bytecode. Each bytecode normally has 1 sequential // successor which is typically made ready by visiting this bytecode. // If the successor has several predecessors, then it is a merge // point, starts a new basic block, and is handled like other basic blocks. //------------------------------merge------------------------------------------ // Collect debug info for inlined calls unless -XX:-DebugInlinedCalls. // Update the JVMS annotation, if present. //------------------------------merge------------------------------------------ // Merge the current mapping into the basic block starting at bci //-------------------------merge_new_path-------------------------------------- // Merge the current mapping into the basic block, using a new path //-------------------------merge_exception------------------------------------- // Merge the current mapping into the basic block starting at bci // The ex_oop must be pushed on the stack, unlike throw_to_exit. assert(
sp() ==
1,
"must have only the throw exception on the stack");
//--------------------handle_missing_successor--------------------------------- //--------------------------merge_common--------------------------------------- // Zap extra stack slots to top // If this path is dead, do not bother capturing it as a merge. // It is "as if" we had 1 fewer predecessors from the beginning. // Record that a new block has been merged. // Make a region if we know there are multiple or unpredictable inputs. // (Also, if this is a plain fall-through, we might see another region, // which must not be allowed into this block's map.) // Add a Region to start the new basic block. Phis will be added // zap all inputs to NULL for debugging (done in Node(uint) constructor) // for (int j = 1; j < edges+1; j++) { r->init_req(j, NULL); } // Convert the existing Parser mapping into a mapping at this bci. }
else {
// Prior mapping at this bci // We must not manufacture more phis if the target is already parsed. // Iterate over my current mapping and the old mapping. // Where different, insert Phi functions. // Use any existing Phi functions. // Compute where to merge into // Merge incoming control path if (
pnum ==
1) {
// Last merge for this Region? // Update all the non-control inputs to map: Node* m =
map()->
in(j);
// Current state of target. Node* n =
newin->
in(j);
// Incoming change to target state. if (m != n) {
// Different; must merge // Frame pointer and Return Address never changes default:
// All normal stuff // At this point, n might be top if: // - there is no phi (because TypeFlow detected a conflict), or // - the corresponding control edges is top (a dead incoming path) // It is a bug if we create a phi which sees a garbage value on a live path. // Last merge for this Phi. // So far, Phis have had a reasonable type from ciTypeFlow. // Now _gvn will join that with the meet of current inputs. // BOTTOM is never permissible here, 'cause pessimistically // Phis of pointers cannot lose the basic pointer type. }
// End of for all values to be merged !r->
in(0)) {
// The occasional useless Region // newin has been subsumed into the lazy merge, and is now dead. stop();
// done with this guy, for now // Done with this parser state. //--------------------------merge_memory_edges--------------------------------- // (nophi means we must not create phis, because we already parsed here) // Merge the inputs to the MergeMems // Trouble: No new splits allowed after a loop body is parsed. // Instead, wire the new split into a MergeMem on the backedge. // The optimizer will sort it out, slicing the phi. // Insert q into local phi base =
phi;
// delay transforming it // Transform base last, in case we must fiddle with remerging. //------------------------ensure_phis_everywhere------------------------------- // Ensure a phi on all currently known memories. // Note: This is our only chance to create phis for memory slices. // If we miss a slice that crops up later, it will have to be // merged into the base-memory phi that we are building here. // Later, the optimizer will comb out the knot, and build separate // phi-loops for each memory slice that matters. // Monitors must nest nicely and not get confused amongst themselves. // Phi-ify everything up to the monitors, though. // Even monitors need Phis, though they are well-structured. // This is true for OSR methods, and also for the rare cases where // a monitor object is the subject of a replace_in_map operation. // See bugs 4426707 and 5043395. //-----------------------------add_new_path------------------------------------ // Add a previously unaccounted predecessor to this block. // If there is no map, return the lowest unused path number. return pred_count()+
1;
// there may be a region some day // Add new path to the region. // Ensure a phi on all currently known memories. //------------------------------ensure_phi------------------------------------- // Turn the idx'th entry of the current map into a Phi if (o ==
top())
return NULL;
// TOP always merges into TOP // Now use a Phi here for merging t = o->
bottom_type();
// Type::RETURN_ADDRESS or such-like. assert(
false,
"no type information for this phi");
// If the type falls to bottom, then this must be a local that // is mixing ints and oops or some such. Forcing it to top // Do not create phis for top either. // A top on a non-null control flow must be an unused even after the.phi. //--------------------------ensure_memory_phi---------------------------------- // Turn the idx'th slice of the current memory into a Phi // clone the shared base memory phi to make a new memory split // Now use a Phi here for merging //------------------------------call_register_finalizer----------------------- // Check the klass of the receiver and call register_finalizer if the // class need finalization. "must have non-null instance type");
// The type isn't known exactly so see if CHA tells us anything. // No finalizable subclasses so skip the dynamic check. // Insert a dynamic test for whether the instance needs // finalization. In general this will fold up since the concrete // class is often visible so the access flags are constant. // There is no slow path. // These two phis are pre-filled with copies of of the fast IO and Memory //------------------------------return_current--------------------------------- // Append current _map to _exit_return // Do not set_parse_bci, so that return goo is credited to the return insn. // get a copy of the base memory, and patch just this one input // frame pointer is always same, already captured // If returning oops to an interface-return, there is a silent free // cast from oop to interface allowed by the Verifier. Make it explicit // sharpen the type eagerly; this eases certain assert checking //------------------------------add_safepoint---------------------------------- // See if we can avoid this safepoint. No need for a SafePoint immediately // after a Call (except Leaf Call) or another SafePoint. // Clear out dead values from the debug info. // Capture memory state BEFORE a SafePoint. Since we can block at a // SafePoint we need our GC state to be safe; i.e. we need all our current // write barriers (card marks) to not float down after the SafePoint so we // must read raw memory. Likewise we need all oop stores to match the card // marks. If deopt can happen, we need ALL stores (we need the correct JVM // We do not need to WRITE the memory state after a SafePoint. The control // edge will keep card-marks and oop-stores from floating up from below a // SafePoint and our true dependency added here will keep them from floating // down below a SafePoint. // Clone the current memory state // Pass control through the safepoint // Fix edges normally used by a call // Create a node for the polling address // Fix up the JVM State edges // Provide an edge from root to safepoint. This makes the safepoint // appear useful until the parse has completed. //------------------------------should_add_predicate-------------------------- //------------------------------add_predicate--------------------------------- //------------------------show_parse_info-------------------------------------- // Check this is not the final compiled version // Print that we succeeded; suppress this message on the first osr parse. // Check this is not the final compiled version //------------------------------dump------------------------------------------- // Dump information associated with the bytecodes of current _method // Iterate over bytecodes // Dump information associated with a byte code index, 'bci' // Output info on merge-points, cloning, and within _jsr..._ret