3909N/A * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 893N/A * Copyright 2008, 2009, 2010 Red Hat, Inc. 893N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 893N/A * This code is free software; you can redistribute it and/or modify it 2362N/A * under the terms of the GNU General Public License version 2 only, as 893N/A * published by the Free Software Foundation. 893N/A * This code is distributed in the hope that it will be useful, but WITHOUT 893N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 893N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 893N/A * version 2 for more details (a copy is included in the LICENSE file that 893N/A * accompanied this code). 893N/A * You should have received a copy of the GNU General Public License version 893N/A * 2 along with this work; if not, write to the Free Software Foundation, 893N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 893N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA // If typeflow found a trap then don't scan past it // Scan the bytecode for traps that are always hit // If the bytecode does not match the field then bail out to // the interpreter to throw an IncompatibleClassChangeError // Bail out if we are trying to access a static variable // before the class initializer has completed. // Bail out if the class is unloaded // Bail out if the class cannot be instantiated // Trap if typeflow trapped (and we didn't before) // This code is lifted pretty much verbatim from C2's // Parse::static_field_ok_in_clinit() in parse3.cpp. // It's OK to access static fields from the class initializer // It's also OK to access static fields inside a constructor, // because any thread calling the constructor must first have // synchronized on the class by executing a "new" bytecode. // This block requires phis: // - if it is entered more than once // - if it is an exception handler, because in which // case we assume it's entered more than once. // - if the predecessor will be compiled after this // block, in which case we can't simple propagate // If this block falls through to the next then it won't have been // terminated by a bytecode and we have to add the branch ourselves // XXX now with Linear Search Technology (tm) // we use an unsigned comparison to catch negative values // The top monitor is marked live, but the exception was thrown // while setting it up so we need to mark it dead before we enter // any exception handlers as they will not expect it to be there. // Try and get this exception's handler from typeflow. We should // do it this way always, really, except that typeflow sometimes // doesn't record exceptions, even loaded ones, and sometimes it // returns them with a different handler bci. Why??? // If typeflow let us down then try and figure it out ourselves // Clear the stack and push the exception onto it // Work out how many options we have to check // Marshal any non-catch-all handlers // Install the catch-all handler, if present // No exception handler was found; unwind and return // Protect our exception across possible monitor release decaches // We don't need to check for exceptions thrown here. If // we're returning a value then we just carry on as normal: // the caller will see the pending exception and handle it. // If we're returning with an exception then that exception // takes priority and the release_lock one will be ignored. // Reload the exception we're throwing // You might expect that array->type()->is_array_klass() would // always be true, but it isn't. If ciTypeFlow detects that a // value is always null then that value becomes an untyped null // object. Shark doesn't presently support this, so a generic // T_OBJECT is created. In this case we guess the type using // the BasicType we were supplied. In reality the generated // code will never be used, as the null value will be caught // by the above null pointer check. // XXX assignability check // All propagation of state from one block to the next (via // dest->add_incoming) is handled by these methods: for (
int i = 0; i <
len; i++) {
// If the method is obviously final then we are already done // Array methods are all inherited from Object and are monomorphic // This code can replace a virtual call with a direct call if this // class is the only one in the entire set of loaded classes that // implements this method. This makes the compiled code dependent // on other classes that implement the method not being loaded, a // condition which is enforced by the dependency tracker. If the // dependency tracker determines a method has become invalid it // will mark it for recompilation, causing running copies to be // deoptimized. Shark currently can't deoptimize arbitrarily like // that, so this optimization cannot be used. // All other interesting cases are instance classes // Attempt to improve the receiver // Attempt to find a monomorphic target for this call using // class heirachy analysis. // Opto has a bunch of type checking here that I don't // understand. It's to inhibit casting in one direction, // possibly because objects in Opto can have inexact // types, but I can't even tell which direction it // doesn't like. For now I'm going to block *any* cast. warning(
"found monomorphic target, but inhibited cast:");
// Replace the virtual call with a direct one. This makes // us dependent on that target method not getting overridden // by dynamic class loading. // Because Opto distinguishes exact types from inexact ones // it can perform a further optimization to replace calls // with non-monomorphic targets if the receiver has an exact // type. We don't mark types this way, so we can't do this. #
endif // SHARK_CAN_DEOPTIMIZE_ANYWHERE // Locate the receiver's itable // Locate this interface's entry in the table // A null entry means that the class doesn't implement the // interface, and wasn't the same as the class checked when // the interface was resolved. // Locate the method pointer // Set frequently used booleans // Find the method being called // Find the class of the method being called. Note // that the superclass check in the second assertion // is to cope with a hole in the spec that allows for // invokeinterface instructions where the resolved // method is a virtual method in java.lang.Object. // javac doesn't generate code like that, but there's // no reason a compliant Java compiler might not. // Find the receiver in the stack. We do this before // trying to inline because the inliner can only use // zero-checked values, not being able to perform the // Try to improve non-direct calls // Try to inline the call // Find the method we are calling // Load the SharkEntry from the callee // Load the entry point from the SharkEntry // If the callee got deoptimized then reexecute in the interpreter // Check for pending exceptions // Mark that a safepoint check has occurred // If the class we're checking against is java.lang.Object // then this is a no brainer. Apparently this can happen // Perform a subtype check. NB in opto's code for this // (GraphKit::static_subtype_check) it says that static // interface types cannot be trusted, and if opto can't // trust them then I assume we can't either. // Get the class we're checking against // Get the class of the object we're checking // Can we optimize this check away? // Need to check this one at runtime // Get the class we're checking against // If the class is unloaded then the instanceof // cannot possibly succeed. // Keep a copy of the object we're checking // Get the class of the object we're checking // If the instanceof can be optimized away at compile time // then any subsequent checkcasts will be too so we handle // Perform the instance check // Create the casted object // Create two copies of the current state, one with the // original object and one with all instances of the // original object replaced with the new, casted object. // Perform the check-and-branch // branch if not an instance // Pop the object off the stack // Null objects aren't instances of anything // Get the class we're checking against // Get the class of the object being tested // Leave the object on the stack so it's there if we trap // If it's not null then we need to trap // If it's null then we're ok // Thread local allocation // The dimensions are stack values, so we use their slots for the // dimensions array. Note that we are storing them in the reverse // of normal stack order. for (
int i = 0; i <
ndims; i++) {
// Now we can pop the dimensions off the stack for (
int i = 0; i <
ndims; i++)
pop();
// don't need this (monitors are block structured) // Store the object and mark the slot as live // Locking failed, but maybe this thread already owns it // NB we use the entire stack, but JavaThread::is_lock_owned() // uses a more limited range. I don't think it hurts though... // Create an edge for the state merge // It's not a recursive case so we need to drop into the runtime // If it is recursive then we're already done // Create an edge for the state merge // Need to drop into the runtime to release this one // The object slot is now dead