stringopts.cpp revision 2230
1472N/A * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 1080N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1080N/A * This code is free software; you can redistribute it and/or modify it 1080N/A * under the terms of the GNU General Public License version 2 only, as 1080N/A * published by the Free Software Foundation. 1080N/A * This code is distributed in the hope that it will be useful, but WITHOUT 1080N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1080N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1080N/A * version 2 for more details (a copy is included in the LICENSE file that 1080N/A * You should have received a copy of the GNU General Public License version 1080N/A * 2 along with this work; if not, write to the Free Software Foundation, 1080N/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 1080N/A // indicating how to treat the value. 1080N/A // to restart at the initial JVMState. 1080N/A // Mode for converting arguments to Strings 1080N/A // XXX This is place holder code for reusing an existing String 1080N/A // allocation but the logic for checking the state safety is 1080N/A // probably inadequate at the moment. 1080N/A // Found useless new String(sb.toString()) so reuse the newly allocated String 1080N/A // when creating the result instead of allocating a new one. 1080N/A log->
head(
"replace_string_concat arguments='%d' string_alloc='%d' multiple='%d'",
1080N/A // Build a new call using the jvms state of the allocate 1080N/A // Set the trap request to record intrinsic failure if this trap 1080N/A // is taken too many times. Ideally we would handle then traps by 1080N/A // doing the original bookkeeping in the MDO so that if it caused 1080N/A // the code to be thrown out we could still recompile and use the 1080N/A // optimization. Failing the uncommon traps doesn't really mean 1080N/A // that the optimization is a bad idea but there's no other way to 1080N/A // do the MDO updates currently. 1080N/A // disconnect the hook node 1080N/A // replace the toString result with the all the arguments that 1080N/A // made up the other StringConcat 1080N/A // EA can't cope with the partially collapsed graph this 1080N/A // creates so put it on the worklist to be collapsed later. 1080N/A // Eliminate Initialize node. 1080N/A // possible opportunity for StringBuilder fusion 1080N/A // Find the constructor call 1080N/A // strange looking allocation 1080N/A // Matched the constructor. 1080N/A // StringBuilder(String) so pick this up as the first argument 1978N/A // StringBuilder(null) throws exception. 1978N/A tty->
print(
"giving up because StringBuilder(null) throws exception");
1978N/A // StringBuilder(str) argument needs null check. 1080N/A // The int variant takes an initial size for the backing 1080N/A // array so just treat it like the void version. 1080N/A // couldn't find constructor 1080N/A // Walked all the way back and found the constructor call so see 1080N/A // if this call converted into a direct string concatenation. 1080N/A // some unhandled signature 1080N/A // Something wrong so give up. 1080N/A // Collect the types needed to talk about the various slices of memory 1080N/A // For each locally allocated StringBuffer see if the usages can be 1080N/A // collapsed into a single String construction. 1080N/A // Run through the list of allocation looking for SB.toString to see 1080N/A // if it's possible to fuse the usage of the SB into a single String 1080N/A // try to coalesce separate concats 1080N/A // Delete any dead nodes to make things clean enough that escape 1080N/A // analysis doesn't get unhappy. 1080N/A // Recurisvely clean up references to CreateEx so EA doesn't 1080N/A // get unhappy about the partially collapsed graph. 1080N/A // We found all the calls and arguments now lets see if it's 1080N/A // safe to transform the graph as we would expect. 1080N/A // Check to see if this resulted in too many uncommon traps previously 1080N/A // Walk backwards over the control flow from toString to the 1080N/A // allocation and make sure all the control flow is ok. This 1080N/A // means it's either going to be eliminated once the calls are 1080N/A // removed or it can safely be transformed into an uncommon 1080N/A // Collect the nodes that we know about and will eliminate into ctrl_path 1080N/A // Push the call and it's control projection 1080N/A // Skip backwards through the control checking for unexpected contro flow 1080N/A // Null check of the return of append which can simply be eliminated 1080N/A // NULL check of the return value of the append 1080N/A // A test which leads to an uncommon trap which should be safe. 1080N/A // Later this trap will be converted into a trap that restarts 1080N/A // control flow leads to uct so should be ok 1080N/A // Some unexpected control flow we don't know how to handle. 1080N/A // XXX should check for possibly merging stores. simple data merges are ok. 1080N/A // Validate that all these results produced are contained within 1080N/A // this cluster of objects. First collect all the results produced 1080N/A // This can happen if the constant oop is non-perm. 1080N/A // Do not "join" in the previous type; it doesn't add value, 1080N/A // and may yield a vacuous result if the field is of interface type. 1080N/A // int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); 2230N/A // Add loop predicate first. 1080N/A // need to handle Integer.MIN_VALUE specially because negating doesn't make it positive 1080N/A // Statically not equal to MIN_VALUE so this path is dead 1080N/A // Simplified version of Integer.getChars 1080N/A // r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... 1080N/A // buf [--charPos] = digits [r]; 2230N/A // Add loop predicate first. 1080N/A // For small constant strings just emit individual stores. 1080N/A for (
int e = 0; e < c; e++) {
1080N/A // Log a little info about the transformation 1080N/A // pull the JVMState of the allocation into a SafePointNode to serve as 1080N/A // as a shim for the insertion of the new code. 1080N/A // copy the control and memory state from the final call into our 1080N/A // new starting state. This allows any preceeding tests to feed 1080N/A // into the new section of code. 1080N/A // blow away old allocation arguments 1080N/A // Copy the rest of the inputs for the JVMState 1080N/A // Make sure the memory state is a MergeMem for parsing. 1080N/A // disconnect all the old StringBuilder calls from the graph 1080N/A // At this point all the old work has been completely removed from 1080N/A // the graph and the saved JVMState exists at the point where the 1080N/A // final toString call used to be. 1080N/A // There may be uncommon traps which are still using the 1080N/A // intermediate states and these need to be rewritten to point at 1080N/A // the JVMState at the beginning of the transformation. 1080N/A // Now insert the logic to compute the size of the string followed 1080N/A // by all the logic to construct array and resulting string. 1080N/A // Create a region for the overflow checks to merge into. 1080N/A // Create a hook node to hold onto the individual sizes since they 1080N/A // are need for the copying phase. 1080N/A // Cache this value for the use by int_toString 1978N/A // Null check with uncommont trap since 1978N/A // StringBuilder(null) throws exception. 1978N/A // Use special uncommon trap instead of 1978N/A // calling normal do_null_check(). 1978N/A // Fallthrough to add string length. 1080N/A // replace the argument with the null checked version 1080N/A // s = s != null ? s : "null"; 1080N/A // length = length + (s.count - s.offset); 1080N/A // replace the argument with the null checked version 1080N/A // Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset), 1080N/A // TypeInt::INT, T_INT, offset_field_idx); 1080N/A // Check that the sum hasn't overflowed 1080N/A // length now contains the number of characters needed for the 1080N/A // char[] so create a new AllocateArray for the char[] 1080N/A // The original jvms is for an allocation of either a String or 1080N/A // StringBuffer so no stack adjustment is necessary for proper 1080N/A // reexecution. If we deoptimize in the slow path the bytecode 1080N/A // will be reexecuted and the char[] allocation will be thrown away. 1080N/A // Mark the allocation so that zeroing is skipped since the code 1080N/A // below will overwrite the entire array 1080N/A // Now copy the string representations into the final char[] 1080N/A // getChars words backwards so pass the ending point as well as the start 1080N/A // If we're not reusing an existing String allocation then allocate one here. 1080N/A // The original jvms is for an allocation of either a String or 1080N/A // StringBuffer so no stack adjustment is necessary for proper 1080N/A // hook up the outgoing control and result