From 3e1688a8cd8754fc5e3a8e15a070e91c4c1370c7 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 18 Feb 2010 15:05:10 -0800 Subject: [PATCH 01/33] 6663854: assert(n != __null,"Bad immediate dominator info.") in C2 with -Xcomp Reviewed-by: kvn --- hotspot/src/share/vm/opto/split_if.cpp | 12 +- .../test/compiler/6663854/Test6663854.java | 1521 +++++++++++++++++ 2 files changed, 1532 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/compiler/6663854/Test6663854.java diff --git a/hotspot/src/share/vm/opto/split_if.cpp b/hotspot/src/share/vm/opto/split_if.cpp index 75ba440a6bd..7b0494d83fc 100644 --- a/hotspot/src/share/vm/opto/split_if.cpp +++ b/hotspot/src/share/vm/opto/split_if.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,10 +187,20 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { } #endif + // ConvI2L may have type information on it which becomes invalid if + // it moves up in the graph so change any clones so widen the type + // to TypeLong::INT when pushing it up. + const Type* rtype = NULL; + if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::INT) { + rtype = TypeLong::INT; + } + // Now actually split-up this guy. One copy per control path merging. Node *phi = PhiNode::make_blank(blk1, n); for( uint j = 1; j < blk1->req(); j++ ) { Node *x = n->clone(); + // Widen the type of the ConvI2L when pushing up. + if (rtype != NULL) x->as_Type()->set_type(rtype); if( n->in(0) && n->in(0) == blk1 ) x->set_req( 0, blk1->in(j) ); for( uint i = 1; i < n->req(); i++ ) { diff --git a/hotspot/test/compiler/6663854/Test6663854.java b/hotspot/test/compiler/6663854/Test6663854.java new file mode 100644 index 00000000000..af044de271c --- /dev/null +++ b/hotspot/test/compiler/6663854/Test6663854.java @@ -0,0 +1,1521 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6663854 + * @summary assert(n != __null,"Bad immediate dominator info.") in C2 with -Xcomp + * + * @run main/othervm -Xcomp Test6663854 + */ + +// This is a randomly generated test that exposed a crash so don't try +// to make sense of what's it's doing. The output produced is likely +// to be stable but it is not being checked as part of this test. + +final class Test6663854_Class_0 { + final long var_1 = ((byte)1.2510591E38F & - ~ - - - ~3554133935918431232L) << 'g'; + final static long var_2 = 662144491976981504L; + static byte[] var_3; + static byte var_4; + static float var_5; + final short var_6 = 4156; + double var_7; + char var_8 = 'F'; + static long var_9; + char var_10; + + + public Test6663854_Class_0() + { + var_7 = (var_9 = (var_4 = (var_4 = (byte)~ -var_1))); + var_7 = (var_4 = (var_4 = (byte)(var_9 = 690685817))) + ~var_2; + long var_17 = 1755837857030316032L; + var_8 *= (var_7 = var_6); + { + var_4 = (var_4 = (byte)var_6); + } + var_5 = (var_4 = (var_4 = (var_4 = (var_4 = (byte)var_17)))); + if (false) + { + var_5 = var_6; + var_4 = (var_4 = (var_4 = (var_4 = (var_4 = (var_4 = (var_4 = (byte)3.2446162E38F)))))); + } + else + { + var_8 &= false ? var_6 : var_6; + } + ((new Test6663854_Class_0[(byte)+ (var_5 = (var_4 = (byte)'Q'))])[var_4 = (byte)396008820]).var_8++; + var_5 = (var_8 ^= var_6 >>> - (var_4 = (byte)var_6)) >= 360526660 ? var_8 : var_8; + } + + + + protected Object clone() + { + char var_11 = 'E'; + var_7 = 1.2181972357945285E308 + var_6 - + (var_7 = 1269180234) * 6.244754764669101E307; + var_7 = (var_4 = (var_4 = (var_4 = (var_4 = (var_4 = (byte)var_11))))); + { + var_4 = (var_4 = (var_4 = (byte)1016847968)); + (false & true ? "nmot" : "m").charAt((false || !true ? var_6 : var_6) * var_6); + var_8 |= var_8-- == (long)(var_7 = (byte)var_2 & ~var_2) ? (var_4 = (var_4 = (var_4 = (var_4 = (byte)1.5012703E38F)))) : (var_4 = (byte)4795604615834685440L); + ++var_11; + var_5 = (var_9 = (int)var_6 | 302324412 - 1720735728); + "yfkasl".replaceAll("xlvn" + "peedfph", "awfbuujts"); + } + var_9 = false ? var_6 : var_6; + { + final boolean var_12 = false; + } + var_5 = var_2; + { + var_9 = ((new byte[(byte)var_6][(byte)1.3719104187525612E308])[var_4 = (byte)var_1])[var_4 = (var_4 = (var_4 = (var_4 = (byte)2.2549062E38F)))] + 889886326; + } + var_9 = (var_2 | ~var_1) & 848602225; + { + var_4 = (var_4 = (var_4 = (var_4 = (byte)var_6))); + } + var_7 = var_6; + var_9 = var_6; + var_5 = (var_4 = (var_4 = (byte)var_8)); + var_7 = 964691433430251520L ^ var_6; + var_5 = ~2571981928559810560L; + return "yvetn".endsWith("dtgstxcu".toLowerCase()) | true | true ? (4.2416016638902373E307 != -3.1295498440444366E307 ? "p" : "ars") : (new Object[(byte)var_1])[(byte)(var_9 = 7519039949758987264L)]; + } + + public boolean equals(Object obj) + { + var_5 = 1445825238; + { + var_7 = 2.221982E38F; + } + { + var_9 = var_6; + } + var_7 = true ? (var_8 ^= (byte)3588201925057082368L) : (var_7 = var_8); + short var_13 = var_6; + var_4 = (var_4 = (var_4 = (var_4 = (var_4 = (byte)'L')))); + var_13--; + return true | !false; + } + + + protected char[] func_0() + { + if (!true ? !false : false) + { + var_8 %= -(new double[(byte)197311342][(byte)5.6183004E36F])[(byte)(var_5 = (var_9 = 'l'))][(byte)(var_7 = var_6)] * (1.9583867E38F * + (var_4 = (byte)1566742425)); + var_8 >>= ~6333520277515092992L | var_8; + } + else + { + new String(); + } + { + var_7 = (byte)5882830303456225280L % ((var_9 = var_6) << var_1); + } + var_7 = var_6; + float var_14; + var_14 = (var_4 = (var_4 = (byte)1081376784)); + var_8 -= 3.1929636E38F; + var_7 = 1.5931970715760934E308; + var_4 = true | (!false | (var_7 = 2.4773615E37F) < (byte)(short)825088022) ? (var_4 = (byte)4.3114896E37F) : (byte)var_8; + final int var_15 = var_6 >> 1197848918; + var_9 = var_15; + var_14 = 983699379; + var_9 = var_6; + return (new char[var_4 = (byte)3.593425789671245E307][(byte)1.6242754453980546E308])[var_4 = (byte)(var_9 = (var_4 = (byte)var_1))]; + } + + final void func_1(final int arg_0) + { + var_5 = 6370513305314412544L == -5.201821E37F ? 2.5220462E38F : (var_5 = (byte)'f'); + ((new Test6663854_Class_0[(byte)1250580004024059904L][(byte)(short)var_8])[(byte)(var_8 ^= 68680455462355968L)][var_4 = (var_4 = (byte)var_2)]).var_8 *= (char)(byte)(var_6 * var_6) <= - (var_7 = (var_7 = var_6)) ? ~5194741848806877184L : var_8; + var_5 = !"tshhykoap".endsWith("q") ? arg_0 : 'K'; + var_8 *= (var_8 -= (var_5 = - (var_5 = var_8))); + int var_16; + } + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_0.var_8 = "; result += Test6663854.Printer.print(var_8); + result += "\n"; + result += "Test6663854_Class_0.var_10 = "; result += Test6663854.Printer.print(var_10); + result += "\n"; + result += "Test6663854_Class_0.var_3 = "; result += Test6663854.Printer.print(var_3); + result += "\n"; + result += "Test6663854_Class_0.var_1 = "; result += Test6663854.Printer.print(var_1); + result += "\n"; + result += "Test6663854_Class_0.var_2 = "; result += Test6663854.Printer.print(var_2); + result += "\n"; + result += "Test6663854_Class_0.var_9 = "; result += Test6663854.Printer.print(var_9); + result += "\n"; + result += "Test6663854_Class_0.var_7 = "; result += Test6663854.Printer.print(var_7); + result += "\n"; + result += "Test6663854_Class_0.var_5 = "; result += Test6663854.Printer.print(var_5); + result += "\n"; + result += "Test6663854_Class_0.var_6 = "; result += Test6663854.Printer.print(var_6); + result += "\n"; + result += "Test6663854_Class_0.var_4 = "; result += Test6663854.Printer.print(var_4); + result += ""; + result += "\n]"; + return result; + } +} + + +interface Test6663854_Interface_1 { + public boolean func_0(); + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3); +} + + +interface Test6663854_Interface_2 extends Test6663854_Interface_1 { +} + + +final class Test6663854_Class_3 implements Test6663854_Interface_2, Test6663854_Interface_1 { + Object var_18; + long var_19; + static double var_20; + final static float var_21 = 2.0644203E38F; + Test6663854_Class_0 var_22; + final static byte var_23 = 110; + static boolean var_24 = false; + + + public Test6663854_Class_3() + { + Test6663854_Class_0.var_5 = new Test6663854_Class_0().var_6; + var_22 = (var_22 = (new Test6663854_Class_0[var_23])[var_23]); + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23)); + char var_37; + var_19 = var_23; + } + + + public boolean func_0() + { + if (var_24 = var_24) + { + Test6663854_Class_0.var_4 = var_24 ^ (var_24 || (var_24 = false)) ? var_23 : (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23)); + } + else + { + ((Test6663854_Class_0)(var_18 = new Test6663854_Interface_1[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23)][var_23])).var_7 = ((var_22 = (var_22 = (Test6663854_Class_0)(var_18 = "uwt"))).var_8 >>>= (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23))); + var_24 |= !false; + } + var_18 = (var_18 = "ymmk"); + if (var_24) + { + long var_25; + ((Test6663854_Class_0)(var_18 = "wsxqujs")).var_8 >>= 'F'; + var_24 ^= false; + } + else + { + { + (var_22 = (Test6663854_Class_0)(var_18 = (var_18 = (var_18 = "lrgiwpwet")))).var_8++; + } + { + var_18 = new String[Test6663854_Class_0.var_4 = var_23]; + } + { + new String(); + } + ((var_24 |= var_24) | true ^ false ? (var_22 = (Test6663854_Class_0)(var_18 = "rpmudju")) : (var_22 = (new Test6663854_Class_0[var_23])[var_23])).var_8--; + var_24 ^= var_24; + var_19 = 206416809; + var_20 = 1581809112; + Test6663854_Class_0 var_26; + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23); + } + byte var_27 = 29; + short var_28 = 24653; + var_22 = (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = "umagt"))); + return var_24; + } + + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3) + { + { + final Test6663854_Class_0 var_29 = (new Test6663854_Class_0[var_23])[arg_2]; + } + var_18 = (var_18 = (var_22 = (Test6663854_Class_0)(var_18 = arg_0))); + ++(var_22 = (Test6663854_Class_0)(var_18 = (Test6663854_Class_0)(var_18 = (var_18 = new char[var_23])))).var_8; + { + (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = "xcj"))).var_8 |= arg_1 * (short)6.671469496987355E307; + Test6663854_Class_0.var_5 = false ? var_23 : 8012291795221583872L; + (var_24 ? (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = arg_0))) : (var_22 = (Test6663854_Class_0)(var_18 = arg_3))).var_8--; + } + ((new String[var_23][var_23])[var_23][var_23]).compareTo(arg_0); + var_18 = (var_18 = arg_0); + var_24 &= (var_24 ^= true) & ! !false; + { + var_18 = "lok"; + } + float var_30 = 2.0346904E38F; + var_30 += ((Test6663854_Class_0)(var_18 = new float[var_23])).var_6 + 210775691; + final double var_31 = 8.865908414454469E307; + var_20 = 'm'; + var_22 = (Test6663854_Class_0)(var_18 = arg_0); + return arg_0; + } + + + protected Object clone() + { + ((Test6663854_Class_0)(var_18 = new short[var_23])).var_7 = 'M'; + if (var_24) + { + var_24 = false; + String var_32 = "luigad"; + ((Test6663854_Class_0.var_5 = 1.2920056E38F) > (Test6663854_Class_0.var_4 = var_23) ? (Test6663854_Class_0)(var_18 = new Test6663854_Interface_1[var_23][var_23]) : (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = new byte[var_23])))).var_10 = 'A'; + (var_22 = (var_22 = (var_22 = (new Test6663854_Class_0[var_23][var_23])[var_23][var_23]))).var_8 /= ((var_22 = (Test6663854_Class_0)(var_18 = (new short[var_23][var_23][var_23])[var_23])).var_7 = 'h'); + (var_32 = var_32).toString(); + var_32.length(); + var_18 = (var_22 = (var_22 = new Test6663854_Class_0())); + } + else + { + Test6663854_Class_0.var_4 = var_23; + var_22 = (var_22 = (Test6663854_Class_0)(var_18 = "wbeuae")); + float var_33; + --(var_22 = (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = (var_18 = "irl"))))).var_8; + } + Test6663854_Class_0.var_4 = var_23; + Test6663854_Class_0.var_5 = true ? ((Test6663854_Class_0)(var_18 = (var_18 = new boolean[Test6663854_Class_0.var_4 = var_23]))).var_8 : 'n'; + var_24 = (var_24 ^= ((var_22 = (Test6663854_Class_0)(var_18 = "g")).var_6 > ((Test6663854_Class_0)(var_18 = "")).var_6 ? var_24 : true) ? false : (var_24 = var_24)) ? var_24 : false; + var_22 = (var_22 = (var_22 = (Test6663854_Class_0)(var_18 = new Test6663854_Interface_2[var_23]))); + return var_18 = "qrlonljqj"; + } + + public boolean equals(Object obj) + { + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23))); + Test6663854_Class_0.var_5 = var_23 % (var_22 = (var_22 = (Test6663854_Class_0)obj)).var_6; + Test6663854_Class_0.var_5 = (((new Test6663854_Class_0[var_23][var_23][var_23])[var_23])[var_24 | (var_24 &= var_24) ? var_23 : (Test6663854_Class_0.var_4 = var_23)][var_23]).var_8; + var_22 = false ? (var_22 = (var_22 = (Test6663854_Class_0)obj)) : (var_22 = new Test6663854_Class_0()); + Test6663854_Class_0.var_5 = ((new Test6663854_Class_0[var_23])[Test6663854_Class_0.var_4 = var_23]).var_8; + if (! !var_24) + { + var_18 = ""; + (var_22 = (var_22 = (var_22 = (new Test6663854_Class_0[var_23])[Test6663854_Class_0.var_4 = var_23]))).var_8 >>= true ? ~ (Test6663854_Class_0.var_4 = var_23) : (var_22 = (Test6663854_Class_0)obj).var_8++; + (var_24 ? (Test6663854_Class_0)(var_18 = "") : (Test6663854_Class_0)obj).var_8 <<= var_23; + Test6663854_Class_0.var_4 = var_23; + var_20 = (var_22 = (var_22 = (var_22 = (var_22 = (Test6663854_Class_0)obj)))).var_8; + } + else + { + var_19 = ((Test6663854_Class_0)obj).var_6; + } + (var_24 ? "qyukxpui" : (new String[var_23])[Test6663854_Class_0.var_4 = var_23]).substring(612084215); + Test6663854_Class_0.var_5 = 'B'; + if (!false || false) + { + Test6663854_Class_0.var_4 = true & var_24 ? var_23 : var_23; + } + else + { + "eksoig".lastIndexOf('b' > (var_22 = (Test6663854_Class_0)obj).var_8 | 4782397447545636864L >= (short)'[' ? "qusgbf" : "kvmylvct"); + } + Test6663854_Class_0.var_5 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = var_23)) << var_23; + int var_34; + var_24 = (var_24 &= (var_24 &= true)); + var_22 = (var_22 = (var_22 = (var_22 = (Test6663854_Class_0)obj))); + Test6663854_Interface_1 var_35 = var_24 & ((var_24 &= var_24) ^ var_24) ? (new Test6663854_Interface_1[var_23])[var_23] : (new Test6663854_Interface_1[var_23][var_23])[var_23][var_23]; + long var_36 = 1042482863045573632L; + return var_24; + } + + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_3.var_19 = "; result += Test6663854.Printer.print(var_19); + result += "\n"; + result += "Test6663854_Class_3.var_20 = "; result += Test6663854.Printer.print(var_20); + result += "\n"; + result += "Test6663854_Class_3.var_21 = "; result += Test6663854.Printer.print(var_21); + result += "\n"; + result += "Test6663854_Class_3.var_23 = "; result += Test6663854.Printer.print(var_23); + result += "\n"; + result += "Test6663854_Class_3.var_24 = "; result += Test6663854.Printer.print(var_24); + result += "\n"; + result += "Test6663854_Class_3.var_22 = "; result += Test6663854.Printer.print(var_22); + result += "\n"; + result += "Test6663854_Class_3.var_18 = "; result += Test6663854.Printer.print(var_18); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Test6663854_Class_4 implements Test6663854_Interface_1, Test6663854_Interface_2 { + long var_38 = (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_23 < (short)+3417996718812544000L) ? ~543562136204028928L : 1593726438; + char var_39; + static Test6663854_Interface_2 var_40; + Test6663854_Class_3 var_41; + final short var_42 = false ? Test6663854_Class_3.var_23 : (short)~Test6663854_Class_0.var_2; + byte var_43; + static Test6663854_Interface_1[] var_44; + final char var_45 = 4.321821176880639E307 < var_42 ? 'o' : 'v'; + + + public Test6663854_Class_4() + { + Test6663854_Class_0.var_5 = 2137855185; + "nueqthqo".length(); + { + Test6663854_Class_0.var_9 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)); + Object var_61; + } + String var_62 = "rirgfphe"; + ((new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_22 = ((var_41 = (var_41 = new Test6663854_Class_3())).var_22 = new Test6663854_Class_0()); + { + Test6663854_Class_0.var_5 = ((new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_42; + new Test6663854_Class_0(); + var_41 = (var_41 = new Test6663854_Class_3()); + new Test6663854_Class_0().var_8 %= var_38; + (var_41 = ((new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_22 = new Test6663854_Class_0(); + Test6663854_Class_0.var_4 = (Test6663854_Class_3.var_24 |= true) ? (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) : Test6663854_Class_3.var_23; + Test6663854_Interface_1 var_63 = ((new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[var_43 = (var_43 = Test6663854_Class_3.var_23)])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]; + (var_41 = (var_41 = (var_41 = (var_41 = (Test6663854_Class_3)var_63)))).var_18 = var_62; + } + if (Test6663854_Class_3.var_24 ^= false) + { + var_40 = (var_40 = new Test6663854_Class_3()); + } + else + { + var_62 = "agwqc"; + Test6663854_Class_3.var_24 ^= ((Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_24 && Test6663854_Class_3.var_24) & false ? false : !Test6663854_Class_3.var_24) ? false | (Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24) : (Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 |= ! (Test6663854_Class_3.var_24 |= true))); + var_38 *= (Test6663854_Class_3.var_20 = (Test6663854_Class_0.var_5 = var_42 + ((Test6663854_Class_3.var_20 = 5378782303770527744L) <= var_42 ? var_42 : var_42))); + } + var_38 &= ((var_41 = new Test6663854_Class_3()).var_22 = new Test6663854_Class_0()).var_6; + var_62 = var_62; + (var_41 = new Test6663854_Class_3()).var_18 = ((new Object[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (var_43 = Test6663854_Class_3.var_23))]; + final short var_64 = (short)'C'; + ((var_41 = new Test6663854_Class_3()).var_22 = new Test6663854_Class_0()).var_8 /= ((var_41 = new Test6663854_Class_3()).var_22 = new Test6663854_Class_0()).var_6; + } + + + public boolean func_0() + { + final boolean var_46 = false; + return Test6663854_Class_3.var_24; + } + + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3) + { + { + --(false ? new Test6663854_Class_0() : new Test6663854_Class_0()).var_8; + "d".substring(Test6663854_Class_3.var_23 - (arg_2 /= + (Test6663854_Class_3.var_20 = 1483190006) * (Test6663854_Class_3.var_20 = ~Test6663854_Class_3.var_23)), 496015226); + { + var_41 = new Test6663854_Class_3(); + } + var_38 ^= (! ((Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24) && (new boolean[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]) ? arg_1 : (var_39 = var_45)) / var_45; + var_38 -= (Test6663854_Class_3.var_20 = (new short[Test6663854_Class_3.var_23])[arg_2]) != (arg_2 ^= new Test6663854_Class_0().var_6 & - (var_38 /= (Test6663854_Class_0.var_5 = var_38))) ? (Test6663854_Class_0.var_5 = - -Test6663854_Class_3.var_21) : arg_2; + var_41 = new Test6663854_Class_3(); + var_40 = Test6663854_Class_3.var_24 ? new Test6663854_Class_3() : new Test6663854_Class_3(); + } + int var_47; + (var_41 = new Test6663854_Class_3()).var_18 = "qvph"; + { + ++arg_2; + } + final Test6663854_Class_3 var_48 = new Test6663854_Class_3(); + { + var_48.var_22 = (Test6663854_Class_0)((var_41 = var_48).var_18 = (var_48.var_22 = (Test6663854_Class_0)(var_48.var_18 = new String[Test6663854_Class_3.var_23]))); + { + final float[] var_49 = (new float[Test6663854_Class_3.var_23][arg_2])[arg_2]; + } + "lcfxrlilw".replace(var_45, (char)(false ? (short)2998890687978943488L : var_42)); + arg_0.lastIndexOf("mx"); + final Test6663854_Class_0 var_50 = var_48.var_22 = (var_48.var_22 = (Test6663854_Class_0)((var_41 = var_48).var_18 = var_48)); + new String(); + ((Test6663854_Class_3)(var_40 = (var_40 = (var_41 = var_48)))).var_22 = var_50; + var_50.var_8 |= arg_2; + Test6663854_Class_3.var_20 = + - (Test6663854_Class_3.var_20 = var_42) - var_45 * Test6663854_Class_3.var_21; + double var_51 = false ? 1.6389923323715952E308 : (var_39 = var_45); + (((new Test6663854_Class_3[arg_2][arg_2])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_18 = (var_48.var_18 = new Test6663854_Class_0[arg_2 %= 2090054678][arg_2]); + } + { + var_47 = (arg_2 |= (((new Test6663854_Class_4[arg_2][arg_2][arg_2])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_42); + } + ((new Test6663854_Class_4[arg_2][Test6663854_Class_3.var_23])[++arg_2][arg_2 <<= 'c']).var_41 = var_48; + var_41 = var_48; + Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24 & Test6663854_Class_3.var_24; + final boolean var_52 = false; + { + var_40 = (var_41 = (var_41 = var_48)); + (false ? var_48 : var_48).var_18 = ((new Test6663854_Class_0[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23][arg_2])[arg_2])[++arg_2][(byte)203097731]; + var_41 = (var_41 = var_48); + } + var_38 |= (short)Test6663854_Class_3.var_23; + var_40 = var_48; + { + arg_0.indexOf("lnf", var_47 = (((Test6663854_Class_0)(var_48.var_18 = arg_0)).var_8 <<= (var_39 = var_45))); + } + final boolean var_53 = true & 1.4130067467800934E308 < (arg_2 |= 'W'); + var_48.var_18 = (var_41 = var_48); + (var_48.var_22 = new Test6663854_Class_0()).var_7 = Test6663854_Class_3.var_23; + Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 || var_52) ^ ("axg".startsWith(arg_0, var_47 = (var_47 = var_45)) | var_52); + { + Test6663854_Class_0.var_5 = 275192701; + } + Test6663854_Interface_2 var_54; + if (true) + { + var_54 = (var_41 = (var_41 = (var_41 = var_48))); + } + else + { + ((Test6663854_Class_0)((var_41 = var_48).var_18 = (var_41 = var_48))).var_7 = var_42; + } + Test6663854_Class_0.var_5 = --arg_2; + ((new String[Test6663854_Class_3.var_23])[var_53 ? arg_2 : arg_2]).length(); + return arg_0 + "qj"; + } + + + + + final String func_0(byte arg_0, Test6663854_Class_0 arg_1, final Test6663854_Class_0 arg_2, final Object arg_3) + { + arg_2.var_7 = (new long[arg_0][arg_0])[Test6663854_Class_3.var_23][arg_0 >>>= 1960882886] % arg_0; + Object var_55 = (((new Test6663854_Class_4[Test6663854_Class_3.var_23])[--arg_0]).var_41 = new Test6663854_Class_3()).var_18 = (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24 ? (Test6663854_Class_3.var_24 |= (Test6663854_Class_3.var_24 &= true)) : Test6663854_Class_3.var_24 | Test6663854_Class_3.var_24) ? (var_41 = (var_41 = (Test6663854_Class_3)arg_3)) : arg_3; + var_38 >>= ((Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_24)) | (Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_24) ? arg_2.var_6 : (arg_0 -= 1.2264686416488313E308)) != (((new Test6663854_Class_4[arg_0])[arg_0]).var_38 >>>= arg_2.var_8) ? Test6663854_Class_3.var_23 : arg_0; + arg_0 += 1826349110 / (Test6663854_Class_0.var_5 = arg_0) + Test6663854_Class_3.var_21; + (var_41 = !Test6663854_Class_3.var_24 ? (var_41 = (new Test6663854_Class_3[arg_0])[arg_0]) : (new Test6663854_Class_3[--arg_0])[arg_0]).var_22 = ((new Test6663854_Class_0[arg_0][(byte)9.18575257519393E307][Test6663854_Class_3.var_23])[arg_0])[Test6663854_Class_3.var_23][arg_0]; + (var_41 = new Test6663854_Class_3()).var_22 = ((var_41 = (var_41 = (var_41 = (var_41 = (var_41 = (Test6663854_Class_3)arg_3))))).var_22 = (arg_1 = arg_2)); + Test6663854_Class_3.var_20 = Test6663854_Class_3.var_21; + var_40 = (var_41 = (Test6663854_Class_3)(new Test6663854_Interface_2[Test6663854_Class_3.var_23])[arg_0]); + Test6663854_Class_0.var_5 = Test6663854_Class_3.var_24 || (Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 &= true)) ? var_42 : arg_1.var_6; + Test6663854_Class_0.var_5 = arg_0; + { + arg_0 %= (short)var_45; + } + var_55 = arg_1; + var_40 = (var_41 = (Test6663854_Class_3.var_24 = false) ? (Test6663854_Class_3)var_55 : (Test6663854_Class_3)arg_3); + ((Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_20 = arg_0) == 2.2107098E38F) ? (Test6663854_Class_3)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[arg_0] : (Test6663854_Class_3)(var_55 = "unofratwy")).var_18 = var_55; + return ""; + } + + private static String func_1(final String arg_0, char arg_1, final boolean arg_2, Test6663854_Class_3 arg_3) + { + if (!false & Test6663854_Class_3.var_24) + { + char var_56 = 'C'; + } + else + { + var_40 = (var_40 = (var_40 = arg_3)); + } + ((new Test6663854_Class_0[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_7 = 2.4396145E38F + (((new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][(byte)Test6663854_Class_0.var_2]).var_43 = Test6663854_Class_3.var_23); + if (Test6663854_Class_3.var_24) + { + arg_3 = arg_3; + } + else + { + arg_3 = (arg_3 = arg_3); + } + ((new Test6663854_Class_4[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_38 /= '`'; + arg_3 = (arg_3 = arg_3); + new Test6663854_Class_0().var_8++; + return "qd"; + } + + private Object func_2(short[][] arg_0, final Test6663854_Interface_2 arg_1) + { + boolean var_57 = false; + Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + var_40 = arg_1; + ((var_41 = (var_41 = (var_41 = (Test6663854_Class_3)arg_1))).var_22 = (Test6663854_Class_0)(((Test6663854_Class_3)arg_1).var_18 = "dxrwk")).var_7 = 'c'; + if (true) + { + var_40 = (var_40 = arg_1); + } + else + { + var_39 = 'Z'; + } + Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + var_41 = (Test6663854_Class_3)arg_1; + return (var_57 ? (Test6663854_Class_3.var_20 = Test6663854_Class_3.var_23) % 1271549437 : 1.1177259470512304E308) <= 1363316667 ? (new Test6663854_Class_3().var_18 = new String[var_43 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]) : new Test6663854_Class_0(); + } + + private short func_3() + { + int var_58 = true ? var_42 : 1438975079; + float var_59 = Test6663854_Class_3.var_21; + var_43 = Test6663854_Class_3.var_23; + (var_41 = (Test6663854_Class_3)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_22 = (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24) ? new Test6663854_Class_0() : new Test6663854_Class_0(); + var_58++; + return Test6663854_Class_3.var_24 ? var_42 : (var_43 = Test6663854_Class_3.var_23); + } + + protected void func_4(final long arg_0, Test6663854_Class_0 arg_1, long arg_2) + { + ++arg_2; + (arg_1 = (arg_1 = (arg_1 = arg_1))).var_8 /= var_42; + --arg_2; + final Test6663854_Interface_1 var_60 = ((new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[var_43 = Test6663854_Class_3.var_23])[var_43 = Test6663854_Class_3.var_23]; + (true ? (Test6663854_Class_3)var_60 : (Test6663854_Class_3)var_60).var_22 = (Test6663854_Class_0)((var_41 = (Test6663854_Class_3)(var_40 = (Test6663854_Class_3)var_60)).var_18 = (Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_23 == var_38) ? "xo" : "uocm"); + var_38 >>= (((Test6663854_Class_3)(new Test6663854_Interface_2[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_22 = (new Test6663854_Class_0[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)]).var_8++; + } + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_4.var_39 = "; result += Test6663854.Printer.print(var_39); + result += "\n"; + result += "Test6663854_Class_4.var_45 = "; result += Test6663854.Printer.print(var_45); + result += "\n"; + result += "Test6663854_Class_4.var_44 = "; result += Test6663854.Printer.print(var_44); + result += "\n"; + result += "Test6663854_Class_4.var_38 = "; result += Test6663854.Printer.print(var_38); + result += "\n"; + result += "Test6663854_Class_4.var_40 = "; result += Test6663854.Printer.print(var_40); + result += "\n"; + result += "Test6663854_Class_4.var_42 = "; result += Test6663854.Printer.print(var_42); + result += "\n"; + result += "Test6663854_Class_4.var_43 = "; result += Test6663854.Printer.print(var_43); + result += "\n"; + result += "Test6663854_Class_4.var_41 = "; result += Test6663854.Printer.print(var_41); + result += ""; + result += "\n]"; + return result; + } +} + + +class Test6663854_Class_5 implements Test6663854_Interface_1 { + final static char var_65 = 'S'; + static Test6663854_Interface_2 var_66; + static Test6663854_Class_3 var_67; + + + public Test6663854_Class_5() + { + { + ((new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)])[((Test6663854_Class_4)(new Object[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_43 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).func_0(); + } + Test6663854_Class_0.var_5 = 1409421143; + Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 = false); + Test6663854_Class_0.var_5 = 3.1496384E38F / (((new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_45 - (Test6663854_Class_3.var_23 + Test6663854_Class_3.var_23)); + ((new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_18 = (new Object[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + var_66 = (Test6663854_Class_4.var_40 = (Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24)) || false ? new Test6663854_Class_3() : new Test6663854_Class_3()); + } + + + public boolean func_0() + { + { + Test6663854_Class_4.var_40 = (new Test6663854_Class_4[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]; + } + Test6663854_Class_0.var_5 = (new char[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + var_66 = (Test6663854_Class_4.var_40 = new Test6663854_Class_3()); + Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + ((var_67 = (var_67 = new Test6663854_Class_3())).var_22 = (Test6663854_Class_0)(new Test6663854_Class_3().var_18 = (new Test6663854_Class_3().var_22 = (new Test6663854_Class_3().var_22 = new Test6663854_Class_0())))).var_8++; + Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + return (Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24) ? (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24) : (Test6663854_Class_3.var_24 = true); + } + + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3) + { + ((true | (Test6663854_Class_3.var_24 |= true)) ^ false ? (new Test6663854_Class_0[(byte)arg_1])[arg_2--] : new Test6663854_Class_0()).var_8 <<= 2320675830599883776L; + arg_2 -= ~ (Test6663854_Class_3.var_24 ? ~4954934861909065728L : 5155213238651986944L); + ((Test6663854_Class_4)((new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[arg_2 >>>= 1308733456])[Test6663854_Class_3.var_23]).var_43 = arg_2; + Test6663854_Class_0.var_5 = Test6663854_Class_3.var_21; + { + String var_68; + float var_69 = Test6663854_Class_3.var_21 * new Test6663854_Class_0().var_6; + ++arg_2; + Test6663854_Class_0.var_9 = arg_2; + --arg_2; + var_68 = arg_0; + final long[] var_70 = new long[arg_2 /= 8889610108908524544L]; + Test6663854_Class_4 var_71; + } + new Test6663854_Class_4().var_38++; + Test6663854_Class_3 var_72; + (((new Test6663854_Class_4[arg_2 *= var_65][Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[arg_2])[arg_2 ^= arg_2][Test6663854_Class_3.var_23]).var_38--; + new Test6663854_Class_3(); + (((new Test6663854_Class_4[arg_2 /= 7.692983E37F][Test6663854_Class_3.var_23])[arg_2])[Test6663854_Class_3.var_23]).var_38 |= arg_1; + Test6663854_Class_3.var_24 ^= "dlhn".startsWith(true ? "tad" : "bssdfvig", 1125165775) ? Test6663854_Class_3.var_24 : true; + Test6663854_Class_3.var_20 = new Test6663854_Class_0().var_8; + Test6663854_Class_4.var_40 = (Test6663854_Class_4.var_40 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]); + var_72 = (new Test6663854_Class_3[Test6663854_Class_3.var_23][arg_2])[arg_2][arg_2]; + Test6663854_Class_0.var_5 = 8634870161778523136L; + { + Test6663854_Class_0.var_5 = ~4420139622226571264L; + Test6663854_Class_3.var_24 &= (var_72 = (var_67 = (new Test6663854_Class_3[arg_2][Test6663854_Class_3.var_23])[arg_2][arg_2])).func_0(); + arg_2 >>= false ? 'H' : ']'; + } + switch (arg_2) + { + case 72: + String var_73 = arg_0; + break; + + default: + + } + ((Test6663854_Class_0)((var_72 = (Test6663854_Class_3)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[arg_2]).var_18 = (Test6663854_Class_4)(new Test6663854_Interface_2[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])).var_7 = ((new Test6663854_Class_0[arg_2])[arg_2]).var_6 + Test6663854_Class_3.var_23; + var_67 = (var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[(byte)7.184837949183326E307][arg_2 ^= 2188582676874919936L]); + return ((Test6663854_Class_3.var_24 = new Test6663854_Class_0().var_6 >= (short)3.4944631475014644E307) ? Test6663854_Class_3.var_24 : (Test6663854_Class_3.var_24 ? (Test6663854_Class_3.var_24 = false) : !Test6663854_Class_3.var_24)) ? "y" : arg_0; + } + + + + + private final static float func_0(boolean arg_0) + { + { + new String(); + { + new String(); + } + ((Test6663854_Class_3)(new Object[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[(new byte[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_18 = (new Object[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[(byte)1.577204008065932E308][Test6663854_Class_3.var_23]; + int var_74; + new String(); + Test6663854_Class_0.var_5 = ((Test6663854_Class_0)(new Object[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_1; + new String(); + new String(); + new String(); + var_74 = '_'; + new Test6663854_Class_0(); + Test6663854_Class_3 var_75 = var_67 = (((new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_41 = (new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]); + } + if (Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24)) + { + new String(); + arg_0 &= ~ (((new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_38 /= Test6663854_Class_3.var_23) < 2.1129417E38F; + } + else + { + Test6663854_Class_3.var_24 &= false & arg_0 ? false : (Test6663854_Class_3.var_24 &= true); + } + new Test6663854_Class_0().var_8 ^= 682270015; + Test6663854_Class_4.var_40 = (Test6663854_Class_4)(new Test6663854_Interface_2[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + new Test6663854_Class_0(); + new String(); + new Test6663854_Class_0(); + new Test6663854_Class_3().var_22 = new Test6663854_Class_0(); + Test6663854_Class_4.var_40 = (new Test6663854_Class_4[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]; + new Test6663854_Class_0().var_8++; + new Test6663854_Class_0(); + Test6663854_Interface_1 var_76; + return Test6663854_Class_3.var_21; + } + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_5.var_65 = "; result += Test6663854.Printer.print(var_65); + result += "\n"; + result += "Test6663854_Class_5.var_66 = "; result += Test6663854.Printer.print(var_66); + result += "\n"; + result += "Test6663854_Class_5.var_67 = "; result += Test6663854.Printer.print(var_67); + result += ""; + result += "\n]"; + return result; + } +} + + +class Test6663854_Class_6 implements Test6663854_Interface_1, Test6663854_Interface_2 { + static long var_77; + final byte var_78 = Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + long var_79; + static Test6663854_Class_4 var_80; + static long var_81 = 1365276905537306624L; + static Test6663854_Class_3 var_82; + + + public Test6663854_Class_6() + { + Test6663854_Class_0.var_5 = Test6663854_Class_3.var_24 ? "bdouannkn".charAt(373674594) : (char)2612074035904901120L; + if (Test6663854_Class_3.var_24) + { + ++var_81; + Test6663854_Class_0.var_4 = (new byte[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)])[var_78]; + var_81++; + } + else + { + (var_80 = (Test6663854_Class_4)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = var_78]).var_41 = (((Test6663854_Class_4)(new Object[Test6663854_Class_3.var_23])[var_78]).var_41 = new Test6663854_Class_3()); + var_81--; + ((new Test6663854_Class_0[var_78])[var_78]).equals((Test6663854_Class_5.var_67 = (Test6663854_Class_3)(new Test6663854_Interface_2[var_78])[var_78]).var_18 = Test6663854_Class_3.var_23 <= var_78 ? "uvoxke" : new String()); + { + Test6663854_Class_5.var_66 = (new Test6663854_Interface_2[var_78])[((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_78]; + } + "huxqcdmii".compareTo("owtdmma"); + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))); + var_81--; + } + { + Test6663854_Class_5[][] var_85; + } + Test6663854_Class_5.var_66 = (new Test6663854_Interface_2[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + if (Test6663854_Class_3.var_24 || Test6663854_Class_3.var_24) + { + var_82 = (new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[var_78][Test6663854_Class_3.var_23]; + Test6663854_Class_0.var_5 = ++var_81; + Test6663854_Class_0.var_5 = Test6663854_Class_3.var_24 ? 'n' : Test6663854_Class_5.var_65; + } + else + { + new Test6663854_Class_0(); + } + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23); + Test6663854_Class_5.var_66 = new Test6663854_Class_3(); + Test6663854_Class_3 var_86 = (var_80 = (var_80 = (var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]))).var_41 = (var_82 = (Test6663854_Class_5.var_67 = ((new Test6663854_Class_3[Test6663854_Class_3.var_23][var_78][Test6663854_Class_3.var_23])[var_78])[var_78][Test6663854_Class_3.var_23])); + Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24) ? (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24) : (Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24); + var_86.var_22 = (new Test6663854_Class_0[var_78][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][var_78]; + (Test6663854_Class_3.var_24 ? "evayayw" : "ndcq").startsWith("hwlik" + "tnhfsky"); + var_86 = var_86; + } + + + public boolean func_0() + { + Test6663854_Class_4.var_40 = (Test6663854_Class_5.var_67 = (new Test6663854_Class_3[var_78])[Test6663854_Class_3.var_23]); + return Test6663854_Class_0.var_2 != (((new Test6663854_Class_0[var_78])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_7 = Test6663854_Class_3.var_23); + } + + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3) + { + Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24; + Test6663854_Class_0.var_5 = var_78; + char var_83; + (Test6663854_Class_5.var_67 = (Test6663854_Class_5.var_67 = (Test6663854_Class_3)(new Test6663854_Interface_1[var_78])[Test6663854_Class_3.var_23])).var_18 = new Test6663854_Class_0[arg_2]; + Test6663854_Class_4 var_84; + var_81++; + return arg_0; + } + + + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_6.var_77 = "; result += Test6663854.Printer.print(var_77); + result += "\n"; + result += "Test6663854_Class_6.var_79 = "; result += Test6663854.Printer.print(var_79); + result += "\n"; + result += "Test6663854_Class_6.var_81 = "; result += Test6663854.Printer.print(var_81); + result += "\n"; + result += "Test6663854_Class_6.var_78 = "; result += Test6663854.Printer.print(var_78); + result += "\n"; + result += "Test6663854_Class_6.var_80 = "; result += Test6663854.Printer.print(var_80); + result += "\n"; + result += "Test6663854_Class_6.var_82 = "; result += Test6663854.Printer.print(var_82); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Test6663854_Class_7 extends Test6663854_Class_5 implements Test6663854_Interface_2 { + final float var_87 = 1.1671899E38F; + static char var_88 = var_65; + float var_89 = 2.166908E37F; + + + public Test6663854_Class_7() + { + var_88--; + (Test6663854_Class_5.var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).equals(((Test6663854_Class_3)(Test6663854_Class_4.var_40 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])).var_18 = "nycb"); + Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24 ^ false); + Test6663854_Class_3.var_24 ^= true; + var_88--; + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]); + if (false) + { + Test6663854_Class_4.var_40 = (new Test6663854_Interface_2[Test6663854_Class_3.var_23])[((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_78]; + } + else + { + --Test6663854_Class_6.var_81; + } + Test6663854_Class_6.var_81--; + ++Test6663854_Class_6.var_81; + if (Test6663854_Class_3.var_24 = !Test6663854_Class_3.var_24) + { + --var_88; + Test6663854_Class_5.var_66 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]; + Test6663854_Class_6.var_81 &= 1451013276; + var_88--; + } + else + { + var_88 >>= --var_88; + } + Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24; + Test6663854_Class_6.var_81--; + Test6663854_Class_6.var_81++; + --Test6663854_Class_6.var_81; + ((new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_41 = new Test6663854_Class_3(); + } + + + + + public final Test6663854_Class_4 func_0(int arg_0) + { + --arg_0; + { + switch ((char)var_89) + { + case 'R': + + } + ++(Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]))).var_38; + ++var_88; + Test6663854_Class_5.var_66 = ~Test6663854_Class_6.var_81 % Test6663854_Class_6.var_81 != (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) ? (Test6663854_Class_6.var_82 = (var_67 = new Test6663854_Class_3())) : new Test6663854_Class_3(); + } + (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)(new Test6663854_Interface_2[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])).var_38 &= new Test6663854_Class_0().var_6; + Test6663854_Interface_1 var_90 = ((new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]; + (Test6663854_Class_5.var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_22 = new Test6663854_Class_0(); + if (true) + { + ((Test6663854_Class_3)(Test6663854_Interface_2)var_90).var_18 = (((Test6663854_Class_3)var_90).var_22 = new Test6663854_Class_0()); + } + else + { + ++((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)var_90)).var_45 > 7.093005581228189E307 ? (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)var_90)) : (Test6663854_Class_4)(var_90 = (Test6663854_Class_3)var_90)).var_38; + } + var_67 = (Test6663854_Class_3.var_24 ^= true) ^ true ? (Test6663854_Class_6.var_82 = (Test6663854_Class_3)var_90) : (Test6663854_Class_3)var_90; + { + { + var_90 = (var_90 = (Test6663854_Class_5)var_90); + } + Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 ? !false : true) ? (Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24))) : ! !Test6663854_Class_3.var_24 && false); + Test6663854_Class_0 var_91; + Test6663854_Class_4.var_40 = (Test6663854_Class_3.var_24 |= (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24) && (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24) | ! (Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_24)) ? (+Test6663854_Class_3.var_21 != 4.6479454E37F ? (Test6663854_Class_6)(Test6663854_Interface_2)var_90 : (Test6663854_Class_6)var_90) : (new Test6663854_Class_6[Test6663854_Class_3.var_23])[((Test6663854_Class_6)(Test6663854_Class_5.var_66 = (Test6663854_Interface_2)var_90)).var_78]; + } + arg_0 |= ((((Test6663854_Class_6.var_80 = (Test6663854_Class_4)var_90).var_41 = (((Test6663854_Class_4)var_90).var_41 = (Test6663854_Class_3)var_90)).var_22 = new Test6663854_Class_0()).var_8 += (Test6663854_Class_3.var_20 = new Test6663854_Class_0().var_1)); + { + (Test6663854_Class_6.var_82 = (new Test6663854_Class_3[((Test6663854_Class_6)var_90).var_78])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_18 = ((Test6663854_Class_3.var_24 ^ (!false & Test6663854_Class_3.var_24 ? Test6663854_Class_3.var_24 : (Test6663854_Class_3.var_24 ^= true)) ? (Test6663854_Class_3)var_90 : (Test6663854_Class_3)(Test6663854_Interface_2)var_90).var_18 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)var_90)).var_41 = (Test6663854_Class_3)(((Test6663854_Class_3)(Test6663854_Class_5.var_66 = (Test6663854_Class_3)var_90)).var_18 = (((Test6663854_Class_3)(Test6663854_Interface_2)var_90).var_18 = (Test6663854_Class_3)var_90)))); + } + { + arg_0++; + } + Test6663854_Interface_2 var_92; + { + ((Test6663854_Class_5.var_67 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_4)(var_92 = (Test6663854_Class_3)var_90)).var_41 = (Test6663854_Class_5.var_67 = (Test6663854_Class_3)var_90))).var_22 = ((Test6663854_Class_5.var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_22 = ((Test6663854_Class_6.var_82 = (((Test6663854_Class_4)var_90).var_41 = (Test6663854_Class_3)var_90)).var_22 = (Test6663854_Class_0)((Test6663854_Class_5.var_67 = (Test6663854_Class_3)var_90).var_18 = (Test6663854_Class_5)var_90)))).var_7 = Test6663854_Class_3.var_21; + } + arg_0 &= ((var_67 = (var_67 = new Test6663854_Class_3())).var_22 = (new Test6663854_Class_0[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_1 / 2084775982; + Test6663854_Class_3.var_20 = (Test6663854_Class_3.var_24 = false) ^ true ? Test6663854_Class_0.var_2 : var_88; + return Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[((Test6663854_Class_6)var_90).var_78]; + } + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_7.var_65 = "; result += Test6663854.Printer.print(var_65); + result += "\n"; + result += "Test6663854_Class_7.var_88 = "; result += Test6663854.Printer.print(var_88); + result += "\n"; + result += "Test6663854_Class_7.var_87 = "; result += Test6663854.Printer.print(var_87); + result += "\n"; + result += "Test6663854_Class_7.var_89 = "; result += Test6663854.Printer.print(var_89); + result += "\n"; + result += "Test6663854_Class_7.var_66 = "; result += Test6663854.Printer.print(var_66); + result += "\n"; + result += "Test6663854_Class_7.var_67 = "; result += Test6663854.Printer.print(var_67); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Test6663854_Class_8 implements Test6663854_Interface_1 { + long var_93 = ++Test6663854_Class_6.var_81; + short var_94 = (short)'H'; + float var_95; + Test6663854_Interface_1 var_96; + final static float var_97 = 2.43397E38F; + final static long var_98 = 7461452158234510336L; + static Test6663854_Class_7[] var_99; + + + public Test6663854_Class_8() + { + Test6663854_Class_6 var_103; + Test6663854_Class_3.var_20 = (Test6663854_Class_3.var_20 = var_94 / ~Test6663854_Class_3.var_23); + if (false) + { + Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24; + } + else + { + Test6663854_Class_3.var_20 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23); + --Test6663854_Class_7.var_88; + } + final boolean[] var_104 = new boolean[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]; + Test6663854_Class_3.var_24 &= false & (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24); + } + + + public boolean func_0() + { + Test6663854_Class_7.var_88--; + Test6663854_Class_7.var_88--; + (((new Test6663854_Class_0[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_7 = 1.2337083709828518E307; + Test6663854_Class_7.var_88++; + if (Test6663854_Class_3.var_24) + { + byte var_100 = 25; + "lwmbav".toLowerCase(); + Test6663854_Class_3.var_24 |= (Test6663854_Class_3.var_24 |= false) & ((Test6663854_Class_3.var_24 = true) ^ Test6663854_Class_3.var_24 ? (Test6663854_Class_3.var_24 ^= Test6663854_Class_3.var_24) : Test6663854_Class_3.var_24); + } + else + { + long var_101; + new Test6663854_Class_0().var_7 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23); + Test6663854_Class_7.var_88++; + ++Test6663854_Class_6.var_81; + Test6663854_Class_7.var_88 |= 1083041050566936576L; + Test6663854_Class_7.var_88--; + } + var_94 ^= (var_94 = (var_94 *= 1.9072213520938263E307)); + var_94++; + boolean var_102 = true; + ++Test6663854_Class_7.var_88; + Test6663854_Class_7.var_88 += (((new Test6663854_Class_7[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_87; + ((new Test6663854_Class_7[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_89 /= (new double[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23] * var_97; + return (Test6663854_Class_3.var_24 = (var_102 &= Test6663854_Class_3.var_24 & true)) ? false : Test6663854_Class_3.var_24; + } + + public String func_1(final String arg_0, final long arg_1, byte arg_2, char[][] arg_3) + { + Test6663854_Class_7.var_88--; + --Test6663854_Class_7.var_88; + return arg_0; + } + + + + private Test6663854_Class_0 func_0(Test6663854_Class_0 arg_0) + { + if (!Test6663854_Class_3.var_24) + { + Test6663854_Class_7.var_88 ^= (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) << ~Test6663854_Class_0.var_2; + } + else + { + (Test6663854_Class_6.var_82 = (Test6663854_Class_7.var_67 = (Test6663854_Class_3)(new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])).var_22 = (((new Test6663854_Class_3[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_22 = (arg_0 = arg_0)); + } + if ((Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))) < Test6663854_Class_3.var_21) + { + Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 ^= (arg_0.var_6 ^ Test6663854_Class_7.var_88++) != (long)"y".codePointAt((int)var_94)) | false; + } + else + { + ++Test6663854_Class_7.var_88; + } + var_94 >>= (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23); + { + Test6663854_Class_7.var_66 = (Test6663854_Class_6)(var_96 = new Test6663854_Class_3()); + } + arg_0.var_8 = 'u'; + var_94 ^= arg_0.var_8; + ++var_94; + Test6663854_Class_7.var_88++; + var_94 += (Test6663854_Class_3.var_20 = '^'); + return arg_0; + } + + public String toString() + { + String result = "[\n"; + result += "Test6663854_Class_8.var_99 = "; result += Test6663854.Printer.print(var_99); + result += "\n"; + result += "Test6663854_Class_8.var_93 = "; result += Test6663854.Printer.print(var_93); + result += "\n"; + result += "Test6663854_Class_8.var_98 = "; result += Test6663854.Printer.print(var_98); + result += "\n"; + result += "Test6663854_Class_8.var_95 = "; result += Test6663854.Printer.print(var_95); + result += "\n"; + result += "Test6663854_Class_8.var_97 = "; result += Test6663854.Printer.print(var_97); + result += "\n"; + result += "Test6663854_Class_8.var_94 = "; result += Test6663854.Printer.print(var_94); + result += "\n"; + result += "Test6663854_Class_8.var_96 = "; result += Test6663854.Printer.print(var_96); + result += ""; + result += "\n]"; + return result; + } +} + +public class Test6663854 { + static short var_105 = 19709; + static int var_106 = (((Test6663854_Class_3.var_24 = (Test6663854_Class_3.var_24 = false)) | true) & (false || !false) ? ! (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24) : Test6663854_Class_3.var_24 | false) ? (short)5430142769559462912L : Test6663854_Class_3.var_23 << Test6663854_Class_3.var_23; + boolean var_107 = false; + + + private static long func_0(final boolean arg_0) + { + { + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)(new Test6663854_Interface_2[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]); + } + var_105++; + ((new Test6663854_Class_7[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)][((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_78]).func_0(); + byte var_108 = 107; + return Test6663854_Class_8.var_98 << ((new Test6663854_Class_4[var_108][Test6663854_Class_3.var_23])[var_108][Test6663854_Class_3.var_24 ? var_108 : var_108--]).var_42; + } + + protected final long func_1(char[] arg_0, Object arg_1, String arg_2, final int arg_3) + { + (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)))).var_43 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)))))).var_43 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)); + { + Test6663854_Class_6.var_82 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)).var_41 = (((new Test6663854[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_107 ^= var_107) ? (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23] : (Test6663854_Class_3)arg_1); + } + Test6663854_Class_7.var_88 += (Test6663854_Class_6.var_81 >>>= (var_107 &= var_107) | var_107 ? (int)- ~Test6663854_Class_6.var_81 : Test6663854_Class_3.var_23); + short var_109 = 11276; + final Test6663854_Class_8 var_110 = (Test6663854_Class_3.var_24 ^ (Test6663854_Class_3.var_24 = !true) ? 5788412835121658880L : var_109--) * (298795405395535872L << (((Test6663854_Class_0)arg_1).var_1 << (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))) != (var_107 ? var_109 : var_105) ? (Test6663854_Class_8)(arg_1 = arg_1) : ((Test6663854_Class_3.var_24 &= ! !var_107) ? new Test6663854_Class_8() : new Test6663854_Class_8()); + new Test6663854_Class_4().var_43 = Test6663854_Class_3.var_24 ^ Test6663854_Class_3.var_24 ^ Test6663854_Class_3.var_24 ? (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)) : (new byte[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1))); + Test6663854_Class_3.var_20 = (var_105 ^= (var_106 *= ((Test6663854_Class_7)arg_1).var_87 - ~Test6663854_Class_3.var_23)); + Test6663854_Class_5 var_111; + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)); + { + (arg_2 = "eiprceumt").compareTo(arg_2 = (arg_2 = "roae")); + } + if (false) + { + final Test6663854_Class_8 var_112 = var_110; + (true | (false && false) ? (Test6663854_Class_3)arg_1 : ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)).var_41 = (Test6663854_Class_6.var_82 = (Test6663854_Class_3)(var_110.var_96 = var_112)))).var_18 = var_110; + } + else + { + (Test6663854_Class_3.var_24 ? "jpunp" : "giappofq").concat(arg_2 = (arg_2 = arg_2)); + } + { + Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24; + } + var_110.var_96 = (Test6663854_Class_7)(var_110.var_96 = (Test6663854_Class_7)arg_1); + { + ((var_107 ^= !var_107) && (!Test6663854_Class_3.var_24 | (Test6663854_Class_3.var_24 |= true) ? !false : !true) ? (Test6663854_Class_4)arg_1 : (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)).var_41 = (((var_107 &= (var_107 &= (var_107 &= (Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24))))) ? (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1) : (Test6663854_Class_4)(Test6663854_Class_4.var_40 = (Test6663854_Class_7)arg_1)).var_41 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)))).var_41 = false || Test6663854_Class_3.var_24 ? (Test6663854_Class_3)arg_1 : (Test6663854_Class_3)arg_1)); + } + Test6663854_Class_5.var_66 = false ? (new Test6663854_Class_6[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23] : new Test6663854_Class_6(); + var_105++; + arg_1 = (var_111 = new Test6663854_Class_7()); + ((true ? (Test6663854_Class_3)arg_1 : (Test6663854_Class_3)arg_1).var_22 = (new Test6663854_Class_0[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_8 >>= (var_106 /= ((Test6663854_Class_4)arg_1).var_42) - ((Test6663854_Class_3.var_24 ? (Test6663854_Class_4)arg_1 : (Test6663854_Class_4)arg_1).var_43 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1))).var_43 = new Test6663854_Class_6().var_78)); + return 5795172173382514688L | (((var_107 &= (Test6663854_Class_3.var_24 |= false) | Test6663854_Class_3.var_24) ? (Test6663854_Class_4)arg_1 : (Test6663854_Class_6.var_80 = (Test6663854_Class_4)arg_1)).var_43 = Test6663854_Class_3.var_23); + } + + public static String execute() + { + try { + Test6663854 t = new Test6663854(); + try { t.test(); } + catch(Throwable e) { } + try { return t.toString(); } + catch (Throwable e) { return "Error during result conversion to String"; } + } catch (Throwable e) { return "Error during test execution"; } + } + + public static void main(String[] args) + { + try { + Test6663854 t = new Test6663854(); + try { t.test(); } + catch(Throwable e) { } + try { System.out.println(t); } + catch(Throwable e) { } + } catch (Throwable e) { } + } + + private void test() + { + if ((true & (false ? !false : true) || var_107 ? (var_105 <<= Test6663854_Class_5.var_65) / (Test6663854_Class_0.var_5 = var_105) : 2509076152709535744L) >= (true ? new Test6663854_Class_8().var_93 : (Test6663854_Class_3.var_20 = Test6663854_Class_3.var_23))) + { + (true ? (new Test6663854_Class_6[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23] : (Test6663854_Class_7.var_66 = new Test6663854_Class_6())).func_0(); + (var_107 ? (new Test6663854_Class_4().var_41 = new Test6663854_Class_3()) : (Test6663854_Class_3)(new Test6663854_Class_3().var_18 = new Test6663854_Class_8())).var_18 = (new Test6663854_Class_4[new Test6663854_Class_4().var_43 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)])[Test6663854_Class_3.var_23]; + { + ++var_106; + ((new Test6663854_Class_5().func_0() ? (Test6663854_Class_3.var_24 ^= true) : !false) ? (Test6663854_Class_7)new Test6663854_Class_5() : (Test6663854_Class_7)((Test6663854_Class_6.var_82 = new Test6663854_Class_3()).var_18 = (Test6663854_Class_6.var_80 = new Test6663854_Class_4()))).var_89 -= Test6663854_Class_3.var_23; + } + var_105 *= 4.59906108270682E307; + { + Test6663854_Class_0.var_4 = ((Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = new Test6663854_Class_4()))).var_43 = (Test6663854_Class_0.var_4 = false ? (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) : Test6663854_Class_3.var_23)); + } + long var_113 = 0L; + var_106 %= (Test6663854_Class_7.var_88 = 'i'); + for (short var_114 = ((Test6663854_Class_8)(new Test6663854_Interface_1[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))])[Test6663854_Class_3.var_23]).var_94; var_113 < 4 && false; "dmmntw".length()) + { + var_114++; + var_113++; + Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24; + new String("kprvouugy"); + } + { + new Test6663854_Class_8().var_94 /= (long)5.719961906225282E307; + } + double var_115 = 0; + Test6663854_Class_3.var_24 |= var_107; + do + { + Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 |= !Test6663854_Class_3.var_24 && var_107); + var_115++; + var_106++; + } while (var_115 < 29 && (var_107 = (Test6663854_Class_3.var_24 |= Test6663854_Class_3.var_24))); + Test6663854_Class_7.var_66 = new Test6663854_Class_7(); + Test6663854_Class_3.var_20 = (false ? (Test6663854_Class_6.var_80 = new Test6663854_Class_4()) : new Test6663854_Class_4()).var_42; + } + else + { + (((new Test6663854_Class_3[Test6663854_Class_3.var_23])[new Test6663854_Class_6().var_78]).var_22 = (new Test6663854_Class_3().var_22 = (new Test6663854_Class_3().var_22 = new Test6663854_Class_0()))).var_8 >>>= (var_106 &= new Test6663854_Class_0().var_8 << Test6663854_Class_7.var_65); + } + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = new Test6663854_Class_4())); + { + Test6663854_Class_8 var_116; + (!true | (Test6663854_Class_3.var_24 &= true) ? new Test6663854_Class_7() : new Test6663854_Class_7()).var_89 /= Test6663854_Class_7.var_88--; + Test6663854_Class_6.var_81 &= ((new Test6663854_Class_6[Test6663854_Class_3.var_23][Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_78; + } + if (true ? var_107 : (Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 |= false))) + { + Test6663854_Class_3.var_24 |= (Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 ^= (Test6663854_Class_3.var_24 &= !true))); + Test6663854_Class_7.var_66 = (Test6663854_Class_7)new Test6663854_Class_5(); + Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))); + { + Test6663854_Class_7.var_88++; + float var_117 = 0F; + final long var_118 = 1388589135930756096L; + for (var_106++; ((Test6663854_Class_3.var_24 &= false) && (Test6663854_Class_3.var_24 |= true)) ^ true && (var_117 < 1 && Test6663854_Class_3.var_24); new Test6663854_Class_0().var_8 += !false || (new float[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23] <= Test6663854_Class_3.var_23 || Test6663854_Class_3.var_24 ? ((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_78 : Test6663854_Class_3.var_23) + { + Test6663854_Class_6.var_82 = (Test6663854_Class_7.var_67 = new Test6663854_Class_3()); + var_117++; + Test6663854_Class_5.var_66 = Test6663854_Class_3.var_24 & !Test6663854_Class_3.var_24 ^ var_107 ^ new Test6663854_Class_0().var_8 == new Test6663854_Class_0().var_1 ? new Test6663854_Class_6() : new Test6663854_Class_6(); + (Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)]).var_43 = (Test6663854_Class_0.var_4 = ((Test6663854_Class_6)(new Object[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_78); + } + if (false & ((var_107 = true) || ! ((Test6663854_Class_3.var_24 ^= true || !var_107) ? false : Test6663854_Class_3.var_24 ^ var_107) ? (var_107 = Test6663854_Class_3.var_24) && Test6663854_Class_3.var_24 : true)) + { + "yvjk".toString(); + } + else + { + Test6663854_Class_4 var_119 = Test6663854_Class_6.var_80 = ((var_107 = true) ? (Test6663854_Class_6.var_81 |= var_106) : var_118) < (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))) ? (Test6663854_Class_4)(new Test6663854_Class_3().var_18 = new float[Test6663854_Class_3.var_23]) : (new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]; + } + (false | (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) >= var_106 ? new Test6663854_Class_3() : (Test6663854_Class_7.var_67 = new Test6663854_Class_3())).var_18 = ((false ? (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23] : new Test6663854_Class_3()).var_22 = ((Test6663854_Class_7.var_67 = (Test6663854_Class_3)(new Test6663854_Class_3().var_18 = (Test6663854_Class_8)(new Test6663854_Class_8().var_96 = new Test6663854_Class_8()))).var_22 = ((Test6663854_Class_5.var_67 = new Test6663854_Class_3()).var_22 = new Test6663854_Class_0()))); + short var_120; + (Test6663854_Class_6.var_80 = new Test6663854_Class_4()).var_41 = new Test6663854_Class_3(); + ((new Test6663854_Class_8[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_96 = (Test6663854_Class_4.var_40 = !false & var_107 ? (Test6663854_Class_7)new Test6663854_Class_5() : new Test6663854_Class_7()); + } + if ((Test6663854_Class_3.var_24 &= (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24)) || Test6663854_Class_3.var_24) + { + { + var_106--; + Test6663854_Class_6.var_81 -= 2.5265952E38F; + Test6663854_Class_7.var_88++; + Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)(new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])); + Test6663854_Class_6.var_81++; + (((new Test6663854_Class_7[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[(byte)(var_105 &= var_106)])[Test6663854_Class_3.var_23]).equals(((new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_18 = new Test6663854_Class_8()); + } + ((((new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_41 = (Test6663854_Class_7.var_67 = (Test6663854_Class_7.var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]))).var_18 = "mnxktbgv"; + var_105++; + ((Test6663854_Class_3.var_24 &= Test6663854_Class_3.var_24) ? (new Test6663854_Class_3().var_22 = new Test6663854_Class_0()) : new Test6663854_Class_0()).var_7 = new Test6663854_Class_0().var_6; + var_105 = (var_105 >>>= Test6663854_Class_3.var_23); + ++var_105; + { + Test6663854_Class_0.var_4 = ((Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_43 = ((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)]).var_78); + ((Test6663854_Class_8)(new Object[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_96 = (Test6663854_Class_6.var_80 = (Test6663854_Class_4)(Test6663854_Class_5.var_66 = (new Test6663854_Class_6[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])); + } + if (2125632862 >= Test6663854_Class_5.var_65) + { + "nfdjgd".toLowerCase(); + ((new Test6663854_Class_8[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]).var_96 = new Test6663854_Class_8(); + Test6663854_Interface_2 var_121; + new Test6663854_Class_0().var_7 = Test6663854_Class_8.var_97; + --var_105; + --Test6663854_Class_7.var_88; + ((new Test6663854_Class_0[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)])[((Test6663854_Class_6)(Test6663854_Class_4.var_40 = (Test6663854_Class_3)(new Object[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])).var_78]).var_7 = (((new Test6663854_Class_8[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_94 += (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)); + } + else + { + --Test6663854_Class_6.var_81; + } + if (false) + { + Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23; + } + else + { + var_105--; + (true | (Test6663854_Class_3.var_24 |= var_107) ? (Test6663854_Class_7)(new Test6663854_Class_5[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23] : (new Test6663854_Class_7[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]).var_89 *= 2.5396491E38F; + var_107 = Test6663854_Class_3.var_24; + var_105++; + } + Test6663854_Class_6.var_81--; + new Test6663854_Class_5(); + } + else + { + Test6663854_Class_0 var_122; + } + var_107 = false; + (Test6663854_Class_3.var_24 ? new Test6663854_Class_7() : (Test6663854_Class_7)(new Test6663854_Class_3().var_18 = new Test6663854_Class_6())).var_89 *= (var_106 -= (new Test6663854_Class_3().var_22 = new Test6663854_Class_0()).var_6); + new Test6663854_Class_8().var_94 *= Test6663854_Class_7.var_88; + ((new String[new Test6663854_Class_6().var_78])[Test6663854_Class_3.var_23]).codePointAt(135817988); + final double var_123 = 7.395191963488875E307; + --var_105; + Test6663854_Class_7.var_88++; + } + else + { + (Test6663854_Class_6.var_80 = Test6663854_Class_3.var_24 ? (Test6663854_Class_6.var_80 = new Test6663854_Class_4()) : (Test6663854_Class_6.var_80 = new Test6663854_Class_4())).var_38 <<= (Test6663854_Class_7.var_88 <<= (new Test6663854_Class_4().var_43 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))) >>> Test6663854_Class_3.var_23); + } + int var_124 = 0; + Test6663854_Class_7 var_125; + float var_126 = 2.5216562E38F; + int var_127 = 0; + Test6663854_Class_7.var_66 = (Test6663854_Class_5.var_66 = (Test6663854_Class_4)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]); + while (var_127 < 1 && (Test6663854_Class_3.var_24 ? (var_107 |= var_107) : false)) + { + short var_128; + var_127++; + var_125 = (var_125 = (var_125 = (var_125 = (Test6663854_Class_7)(new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]))); + "nkv".indexOf("ptrepiu" + "aljmjttym", var_106 << (new byte[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]); + } + { + Test6663854_Class_7.var_66 = (Test6663854_Class_7.var_67 = (new Test6663854_Class_3[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]); + } + var_125 = (new Test6663854_Class_7[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]; + var_126 += var_106; + while (var_124 < 537 && true) + { + Test6663854_Class_7.var_88 %= var_105; + var_124++; + var_106++; + Test6663854_Class_5.var_66 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])); + final long var_129 = 3230407753980990464L; + new Test6663854_Class_8(); + final Test6663854_Class_3 var_130 = (Test6663854_Class_3)((Test6663854_Class_3.var_24 |= !false) | (var_107 | !var_107) | (new Test6663854_Class_8().var_94++ >= 1015752753 | !true) ? (new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23] : (new Test6663854_Interface_1[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23]); + Test6663854_Class_5.var_66 = (Test6663854_Class_7.var_66 = (Test6663854_Class_7.var_66 = (Test6663854_Class_7.var_67 = var_130))); + } + Test6663854_Class_7.var_66 = var_126 >= (Test6663854_Class_3.var_24 || (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24) ? var_106 : var_126) ? new Test6663854_Class_6() : new Test6663854_Class_6(); + var_107 &= true; + (new Test6663854_Class_8().var_96 = (var_125 = (var_125 = (var_125 = new Test6663854_Class_7())))).func_0(); + float var_131 = 0F; + Test6663854_Class_3 var_132 = new Test6663854_Class_3(); + do + { + long var_133; + var_131++; + Test6663854_Interface_2 var_134 = Test6663854_Class_7.var_66 = var_132; + } while ((Test6663854_Class_3.var_24 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23) == 1.2758309E38F) && (var_131 < 117 && ((new short[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)] == ((var_107 &= ! (Test6663854_Class_3.var_24 ^= false)) ^ ! !false ? new Test6663854_Class_0().var_6 : new Test6663854_Class_4().var_42))); + (var_107 ? var_132 : (Test6663854_Class_3)(Test6663854_Class_7.var_66 = var_132)).var_18 = (Test6663854_Class_0)((Test6663854_Class_5.var_67 = (Test6663854_Class_7.var_67 = (var_132 = var_132))).var_18 = ((new Test6663854_Class_8[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23))])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]); + long var_135 = 0L; + (((new Test6663854_Class_8[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = (byte)+ (Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23)]).var_96 = var_132; + for (((var_107 = ((new Test6663854_Class_0[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).equals(var_132.var_18 = (Test6663854_Class_8)(new Test6663854_Class_8().var_96 = var_132))) ? "oedsntb" : "ouspr").concat("t"); var_135 < 27; (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23]))).var_38 %= (double)func_0(Test6663854_Class_3.var_24 = false ? !var_107 && ! !Test6663854_Class_3.var_24 : Test6663854_Class_3.var_24 ^ ! (Test6663854_Class_3.var_24 = Test6663854_Class_3.var_24))) + { + Test6663854_Class_6.var_80 = (Test6663854_Class_4)(new Test6663854_Class_8().var_96 = new Test6663854_Class_8()); + var_135++; + Test6663854_Class_3.var_24 &= !true; + new Test6663854_Class_0().var_8 += Test6663854_Class_7.var_65; + } + Test6663854_Class_3 var_136 = var_132; + if ((var_107 = ((Test6663854_Class_4)(Test6663854_Class_7.var_66 = (var_125 = (Test6663854_Class_7)(Test6663854_Class_7.var_66 = var_136)))).func_0() ^ true) && (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (Test6663854_Class_6.var_80 = (new Test6663854_Class_4[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]))).var_45 <= ((new Test6663854_Class_6[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23]).var_78) + { + var_126 %= ((var_107 = true) ? (var_105 *= 8272288534835139584L) : (var_105 |= var_105)) % new Test6663854_Class_7().var_89; + ((Test6663854_Class_3)(new Test6663854_Class_8().var_96 = (new Test6663854_Interface_1[Test6663854_Class_3.var_23])[Test6663854_Class_3.var_23])).var_18 = new Test6663854_Class_0(); + var_105 <<= ++((Test6663854_Class_3.var_24 |= false) ? new Test6663854_Class_8() : (Test6663854_Class_8)(new Test6663854_Class_8().var_96 = new Test6663854_Class_4())).var_94 % (Test6663854_Class_0.var_2 - var_106); + Test6663854_Interface_2 var_137; + var_137 = new Test6663854_Class_4(); + int var_138; + } + else + { + final Test6663854_Interface_2 var_139 = Test6663854_Class_4.var_40 = (var_136 = var_136); + new Test6663854_Class_8().var_93 -= new Test6663854_Class_6().var_78; + --((Test6663854_Class_3.var_24 ^= var_126 < Test6663854_Class_3.var_23 | !var_107) ? (new Test6663854_Class_8[Test6663854_Class_3.var_23][Test6663854_Class_3.var_23])[Test6663854_Class_0.var_4 = Test6663854_Class_3.var_23][new Test6663854_Class_6().var_78] : new Test6663854_Class_8()).var_93; + var_105 >>= ! (Test6663854_Class_3.var_24 = true) || ((Test6663854_Class_8)(! (Test6663854_Class_3.var_24 |= var_107) | (false ? Test6663854_Class_3.var_23 : new Test6663854_Class_6().var_78) != new Test6663854_Class_8().var_93 ? (Test6663854_Class_6.var_82 = var_136) : (new Test6663854_Class_8().var_96 = (var_132 = var_136)))).var_94 >= Test6663854_Class_6.var_81++ ? var_124 : '`'; + } + var_126 /= var_105; + var_105 *= var_127; + var_107 ^= (var_107 = true); + { + Test6663854_Class_7.var_66 = (var_125 = (Test6663854_Class_7)(new Test6663854_Class_5[Test6663854_Class_3.var_23])[new Test6663854_Class_6().var_78]); + } + (var_136.var_22 = ((var_136 = var_132).var_22 = new Test6663854_Class_0())).var_7 = ((!false ? var_132 : (Test6663854_Class_7.var_67 = var_132)).var_22 = (((Test6663854_Class_3)(var_136.var_18 = var_136)).var_22 = (Test6663854_Class_0)(var_132.var_18 = "sgybwy"))).var_6; + ((Test6663854_Class_3.var_20 = var_105--) >= ~Test6663854_Class_3.var_23 ? new String() : "lgcfkbsw").replace(new Test6663854_Class_0().var_8 |= 't', false ? (Test6663854_Class_7.var_88 -= var_105) : 'q'); + Test6663854_Class_7.var_88 <<= Test6663854_Class_7.var_88; + } + public String toString() + { + String result = "[\n"; + result += "Test6663854.var_105 = "; result += Printer.print(var_105); + result += "\n"; + result += "Test6663854.var_107 = "; result += Printer.print(var_107); + result += "\n"; + result += "Test6663854.var_106 = "; result += Printer.print(var_106); + result += ""; + result += "\n]"; + return result; + } + static class Printer + { + public static String print(boolean arg) { return String.valueOf(arg); } + public static String print(byte arg) { return String.valueOf(arg); } + public static String print(short arg) { return String.valueOf(arg); } + public static String print(char arg) { return String.valueOf((int)arg); } + public static String print(int arg) { return String.valueOf(arg); } + public static String print(long arg) { return String.valueOf(arg); } + public static String print(float arg) { return String.valueOf(arg); } + public static String print(double arg) { return String.valueOf(arg); } + + + public static String print(Object arg) + { + return print_r(new java.util.Stack(), arg); + } + + private static String print_r(java.util.Stack visitedObjects, Object arg) + { + String result = ""; + if (arg == null) + result += "null"; + else + if (arg.getClass().isArray()) + { + for (int i = 0; i < visitedObjects.size(); i++) + if (visitedObjects.elementAt(i) == arg) return ""; + + visitedObjects.push(arg); + + final String delimiter = ", "; + result += "["; + + if (arg instanceof Object[]) + { + Object[] array = (Object[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print_r(visitedObjects, array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof boolean[]) + { + boolean[] array = (boolean[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof byte[]) + { + byte[] array = (byte[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof short[]) + { + short[] array = (short[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof char[]) + { + char[] array = (char[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof int[]) + { + int[] array = (int[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof long[]) + { + long[] array = (long[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof float[]) + { + float[] array = (float[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof double[]) + { + double[] array = (double[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + + result += "]"; + visitedObjects.pop(); + + } else + { + result += arg.toString(); + } + + return result; + } + } +} From fa2d360cd5c0a8d57aed7ad6eb6c3b5d0956364a Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 19 Feb 2010 10:04:16 -0800 Subject: [PATCH 02/33] 6910664: C2: java/util/Arrays/Sorting.java fails with DeoptimizeALot flag Matcher::float_in_double should be true only when FPU is used for floats. Reviewed-by: never, twisti --- hotspot/src/cpu/sparc/vm/sparc.ad | 5 +++-- hotspot/src/cpu/x86/vm/x86_32.ad | 6 ++++-- hotspot/src/cpu/x86/vm/x86_64.ad | 6 ++++-- hotspot/src/share/vm/opto/matcher.hpp | 4 ++-- hotspot/src/share/vm/opto/output.cpp | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 73e94021152..0243793479a 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1803,8 +1803,9 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { // to implement the UseStrictFP mode. const bool Matcher::strict_fp_requires_explicit_rounding = false; -// Do floats take an entire double register or just half? -const bool Matcher::float_in_double = false; +// Are floats conerted to double when stored to stack during deoptimization? +// Sparc does not handle callee-save floats. +bool Matcher::float_in_double() { return false; } // Do ints take an entire long register or just half? // Note that we if-def off of _LP64. diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 4fe1fd22df3..4e78eb1b7f1 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -1444,8 +1444,10 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { // to implement the UseStrictFP mode. const bool Matcher::strict_fp_requires_explicit_rounding = true; -// Do floats take an entire double register or just half? -const bool Matcher::float_in_double = true; +// Are floats conerted to double when stored to stack during deoptimization? +// On x32 it is stored with convertion only when FPU is used for floats. +bool Matcher::float_in_double() { return (UseSSE == 0); } + // Do ints take an entire long register or just half? const bool Matcher::int_in_long = false; diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 86e28eed7ea..32e8eaceeaf 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -2074,8 +2074,10 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) {} // implement the UseStrictFP mode. const bool Matcher::strict_fp_requires_explicit_rounding = true; -// Do floats take an entire double register or just half? -const bool Matcher::float_in_double = true; +// Are floats conerted to double when stored to stack during deoptimization? +// On x64 it is stored without convertion so we can use normal access. +bool Matcher::float_in_double() { return false; } + // Do ints take an entire long register or just half? const bool Matcher::int_in_long = true; diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index b48303baa87..8ade05151d1 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -373,8 +373,8 @@ public: // to implement the UseStrictFP mode. static const bool strict_fp_requires_explicit_rounding; - // Do floats take an entire double register or just half? - static const bool float_in_double; + // Are floats conerted to double when stored to stack during deoptimization? + static bool float_in_double(); // Do ints take an entire long register or just half? static const bool int_in_long; diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index fb5db8e7791..5e371e27f0c 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -678,7 +678,7 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, #endif //_LP64 else if( (t->base() == Type::FloatBot || t->base() == Type::FloatCon) && OptoReg::is_reg(regnum) ) { - array->append(new_loc_value( _regalloc, regnum, Matcher::float_in_double + array->append(new_loc_value( _regalloc, regnum, Matcher::float_in_double() ? Location::float_in_dbl : Location::normal )); } else if( t->base() == Type::Int && OptoReg::is_reg(regnum) ) { array->append(new_loc_value( _regalloc, regnum, Matcher::int_in_long From fbd5ca617d77ea5ce41b8f503fbc96336f07aa7f Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 19 Feb 2010 13:06:11 -0800 Subject: [PATCH 03/33] 6927049: assert(is_Loop(),"invalid node class") Reviewed-by: kvn --- hotspot/src/share/vm/opto/loopTransform.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 809f47472c6..0fa5a4086a0 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -2117,6 +2117,18 @@ BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { if (!UseLoopPredicate) return false; + if (!loop->_head->is_Loop()) { + // Could be a simple region when irreducible loops are present. + return false; + } + + CountedLoopNode *cl = NULL; + if (loop->_head->is_CountedLoop()) { + cl = loop->_head->as_CountedLoop(); + // do nothing for iteration-splitted loops + if (!cl->is_normal_loop()) return false; + } + // Too many traps seen? bool tmt = C->too_many_traps(C->method(), 0, Deoptimization::Reason_predicate); int tc = C->trap_count(Deoptimization::Reason_predicate); @@ -2129,13 +2141,6 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { return false; } - CountedLoopNode *cl = NULL; - if (loop->_head->is_CountedLoop()) { - cl = loop->_head->as_CountedLoop(); - // do nothing for iteration-splitted loops - if(!cl->is_normal_loop()) return false; - } - LoopNode *lpn = loop->_head->as_Loop(); Node* entry = lpn->in(LoopNode::EntryControl); From e599f6c92711cf017611bbd71822ce1439c89637 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 22 Feb 2010 16:56:49 -0800 Subject: [PATCH 04/33] 6928717: HS17 fails to build with SS11 C++ Add missing handles.inline.hpp for codeCache.cpp. Reviewed-by: never --- hotspot/src/share/vm/includeDB_core | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 0d1b52513e3..7135f8ef4a0 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -1021,6 +1021,7 @@ codeCache.cpp codeBlob.hpp codeCache.cpp codeCache.hpp codeCache.cpp dependencies.hpp codeCache.cpp gcLocker.hpp +codeCache.cpp handles.inline.hpp codeCache.cpp icache.hpp codeCache.cpp iterator.hpp codeCache.cpp java.hpp From d1a6f819e6eee9021bf09a0e41a938bcf82fd3c2 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 23 Feb 2010 17:46:29 +0100 Subject: [PATCH 05/33] 6928839: JSR 292 typo in x86 _adapter_check_cast There is a small typo in methodHandles_x86.cpp. Reviewed-by: kvn --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index fc11240e030..fa3c5043246 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -584,7 +584,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan Label done; __ movptr(rdx_temp, vmarg); - __ testl(rdx_temp, rdx_temp); + __ testptr(rdx_temp, rdx_temp); __ jccb(Assembler::zero, done); // no cast if null __ load_klass(rdx_temp, rdx_temp); From b5c83abcd4b0b90f7b6aecd30464768eed874e06 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 23 Feb 2010 23:13:23 -0500 Subject: [PATCH 06/33] 6928059: G1: command line parameter renaming Rename G1 parameters to make them more consistent. Reviewed-by: jmasa, johnc --- .../g1/concurrentG1Refine.cpp | 24 +++++------ .../g1/concurrentG1Refine.hpp | 3 +- .../g1/concurrentG1RefineThread.cpp | 18 +++++--- .../gc_implementation/g1/concurrentMark.cpp | 2 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 10 ++--- .../g1/g1CollectorPolicy.cpp | 28 ++++--------- .../vm/gc_implementation/g1/g1MMUTracker.cpp | 6 +-- .../vm/gc_implementation/g1/g1MMUTracker.hpp | 2 +- .../vm/gc_implementation/g1/g1RemSet.cpp | 4 +- .../vm/gc_implementation/g1/g1_globals.hpp | 41 +++++++++---------- 10 files changed, 65 insertions(+), 73 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp index 79874f0df69..db64676b939 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @@ -44,20 +44,20 @@ ConcurrentG1Refine::ConcurrentG1Refine() : { // Ergomonically select initial concurrent refinement parameters - if (FLAG_IS_DEFAULT(G1ConcRefineGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefineGreenZone, MAX2(ParallelGCThreads, 1)); + if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { + FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, MAX2(ParallelGCThreads, 1)); } - set_green_zone(G1ConcRefineGreenZone); + set_green_zone(G1ConcRefinementGreenZone); - if (FLAG_IS_DEFAULT(G1ConcRefineYellowZone)) { - FLAG_SET_DEFAULT(G1ConcRefineYellowZone, green_zone() * 3); + if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { + FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); } - set_yellow_zone(MAX2(G1ConcRefineYellowZone, green_zone())); + set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); - if (FLAG_IS_DEFAULT(G1ConcRefineRedZone)) { - FLAG_SET_DEFAULT(G1ConcRefineRedZone, yellow_zone() * 2); + if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { + FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); } - set_red_zone(MAX2(G1ConcRefineRedZone, yellow_zone())); + set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); _n_worker_threads = thread_num(); // We need one extra thread to do the young gen rset size sampling. _n_threads = _n_worker_threads + 1; @@ -76,15 +76,15 @@ ConcurrentG1Refine::ConcurrentG1Refine() : } void ConcurrentG1Refine::reset_threshold_step() { - if (FLAG_IS_DEFAULT(G1ConcRefineThresholdStep)) { + if (FLAG_IS_DEFAULT(G1ConcRefinementThresholdStep)) { _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1); } else { - _thread_threshold_step = G1ConcRefineThresholdStep; + _thread_threshold_step = G1ConcRefinementThresholdStep; } } int ConcurrentG1Refine::thread_num() { - return MAX2((G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads, 1); + return MAX2((G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads : ParallelGCThreads, 1); } void ConcurrentG1Refine::init() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp index 7bcbecfbe5e..656921c7fb3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp @@ -39,7 +39,8 @@ class ConcurrentG1Refine: public CHeapObj { * running. If the length becomes red (max queue length) the mutators start * processing the buffers. * - * There are some interesting cases (with G1AdaptiveConcRefine turned off): + * There are some interesting cases (when G1UseAdaptiveConcRefinement + * is turned off): * 1) green = yellow = red = 0. In this case the mutator will process all * buffers. Except for those that are created by the deferred updates * machinery during a collection. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp index b23c287a6e5..741aaf65cc2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @@ -107,7 +107,7 @@ void ConcurrentG1RefineThread::run_young_rs_sampling() { if (_should_terminate) { break; } - _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefineServiceInterval); + _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis); } } @@ -127,7 +127,7 @@ bool ConcurrentG1RefineThread::is_active() { void ConcurrentG1RefineThread::activate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (_worker_id > 0) { - if (G1TraceConcurrentRefinement) { + if (G1TraceConcRefinement) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d", _worker_id, _threshold, (int)dcqs.completed_buffers_num()); @@ -143,7 +143,7 @@ void ConcurrentG1RefineThread::activate() { void ConcurrentG1RefineThread::deactivate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (_worker_id > 0) { - if (G1TraceConcurrentRefinement) { + if (G1TraceConcRefinement) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d", _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num()); @@ -218,9 +218,13 @@ void ConcurrentG1RefineThread::run() { void ConcurrentG1RefineThread::yield() { - if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield"); + if (G1TraceConcRefinement) { + gclog_or_tty->print_cr("G1-Refine-yield"); + } _sts.yield("G1 refine"); - if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield-end"); + if (G1TraceConcRefinement) { + gclog_or_tty->print_cr("G1-Refine-yield-end"); + } } void ConcurrentG1RefineThread::stop() { @@ -241,7 +245,9 @@ void ConcurrentG1RefineThread::stop() { Terminator_lock->wait(); } } - if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-stop"); + if (G1TraceConcRefinement) { + gclog_or_tty->print_cr("G1-Refine-stop"); + } } void ConcurrentG1RefineThread::print() const { diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index c77af414161..41966bed1d5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -461,7 +461,7 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency"); SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); - satb_qs.set_buffer_size(G1SATBLogBufferSize); + satb_qs.set_buffer_size(G1SATBBufferSize); int size = (int) MAX2(ParallelGCThreads, (size_t)1); _par_cleanup_thread_state = NEW_C_HEAP_ARRAY(ParCleanupThreadState*, size); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 9b2b71292d8..0f844041e14 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -583,7 +583,7 @@ HeapRegion* G1CollectedHeap::newAllocRegion_work(size_t word_size, res->zero_fill_state() == HeapRegion::Allocated)), "Non-young alloc Regions must be zero filled (and non-H)"); - if (G1PrintRegions) { + if (G1PrintHeapRegions) { if (res != NULL) { gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT", "PTR_FORMAT"], " "top "PTR_FORMAT, @@ -2477,7 +2477,7 @@ void G1CollectedHeap::print_tracing_info() const { if (G1SummarizeRSetStats) { g1_rem_set()->print_summary_info(); } - if (G1SummarizeConcurrentMark) { + if (G1SummarizeConcMark) { concurrent_mark()->print_summary_info(); } if (G1SummarizeZFStats) { @@ -3480,7 +3480,7 @@ void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) { HeapRegion* r = heap_region_containing(old); if (!r->evacuation_failed()) { r->set_evacuation_failed(true); - if (G1PrintRegions) { + if (G1PrintHeapRegions) { gclog_or_tty->print("evacuation failed in heap region "PTR_FORMAT" " "["PTR_FORMAT","PTR_FORMAT")\n", r, r->bottom(), r->end()); @@ -4002,9 +4002,7 @@ public: _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms); _g1h->g1_policy()->record_termination_time(i, term_ms); } - if (G1UseSurvivorSpaces) { - _g1h->g1_policy()->record_thread_age_table(pss.age_table()); - } + _g1h->g1_policy()->record_thread_age_table(pss.age_table()); _g1h->update_surviving_young_words(pss.surviving_young_words()+1); // Clean up any par-expanded rem sets. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 7702c788f21..ad5f37fa00a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -270,14 +270,10 @@ G1CollectorPolicy::G1CollectorPolicy() : _concurrent_mark_cleanup_times_ms->add(0.20); _tenuring_threshold = MaxTenuringThreshold; - if (G1UseSurvivorSpaces) { - // if G1FixedSurvivorSpaceSize is 0 which means the size is not - // fixed, then _max_survivor_regions will be calculated at - // calculate_young_list_target_config during initialization - _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; - } else { - _max_survivor_regions = 0; - } + // if G1FixedSurvivorSpaceSize is 0 which means the size is not + // fixed, then _max_survivor_regions will be calculated at + // calculate_young_list_target_config during initialization + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; initialize_all(); } @@ -455,7 +451,7 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { guarantee( adaptive_young_list_length(), "pre-condition" ); double start_time_sec = os::elapsedTime(); - size_t min_reserve_perc = MAX2((size_t)2, (size_t)G1MinReservePercent); + size_t min_reserve_perc = MAX2((size_t)2, (size_t)G1ReservePercent); min_reserve_perc = MIN2((size_t) 50, min_reserve_perc); size_t reserve_regions = (size_t) ((double) min_reserve_perc * (double) _g1->n_regions() / 100.0); @@ -1110,10 +1106,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, size_t short_lived_so_length = _young_list_so_prefix_length; _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length); tag_scan_only(short_lived_so_length); - - if (G1UseSurvivorSpaces) { - _survivors_age_table.clear(); - } + _survivors_age_table.clear(); assert( verify_young_ages(), "region age verification" ); } @@ -1916,7 +1909,7 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) { calculate_young_list_target_config(); // Note that _mmu_tracker->max_gc_time() returns the time in seconds. - double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSUpdatePauseFractionPercent / 100.0; + double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); // @@ -1932,7 +1925,7 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); ConcurrentG1Refine *cg1r = G1CollectedHeap::heap()->concurrent_g1_refine(); - if (G1AdaptiveConcRefine) { + if (G1UseAdaptiveConcRefinement) { const int k_gy = 3, k_gr = 6; const double inc_k = 1.1, dec_k = 0.9; @@ -2607,9 +2600,6 @@ size_t G1CollectorPolicy::max_regions(int purpose) { // Calculates survivor space parameters. void G1CollectorPolicy::calculate_survivors_policy() { - if (!G1UseSurvivorSpaces) { - return; - } if (G1FixedSurvivorSpaceSize == 0) { _max_survivor_regions = _young_list_target_length / SurvivorRatio; } else { @@ -2867,7 +2857,7 @@ record_concurrent_mark_cleanup_end(size_t freed_bytes, // estimate of the number of live bytes. void G1CollectorPolicy:: add_to_collection_set(HeapRegion* hr) { - if (G1PrintRegions) { + if (G1PrintHeapRegions) { gclog_or_tty->print_cr("added region to cset %d:["PTR_FORMAT", "PTR_FORMAT"], " "top "PTR_FORMAT", young %s", hr->hrs_index(), hr->bottom(), hr->end(), diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp index 492adaef6fd..79f4c78c74f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp @@ -88,13 +88,13 @@ void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) { // the time slice than what's allowed) // consolidate the two entries with the minimum gap between them // (this might allow less GC time than what's allowed) - guarantee(NOT_PRODUCT(ScavengeALot ||) G1ForgetfulMMUTracker, - "array full, currently we can't recover unless +G1ForgetfulMMUTracker"); + guarantee(NOT_PRODUCT(ScavengeALot ||) G1UseFixedWindowMMUTracker, + "array full, currently we can't recover unless +G1UseFixedWindowMMUTracker"); // In the case where ScavengeALot is true, such overflow is not // uncommon; in such cases, we can, without much loss of precision // or performance (we are GC'ing most of the time anyway!), // simply overwrite the oldest entry in the tracker: this - // is also the behaviour when G1ForgetfulMMUTracker is enabled. + // is also the behaviour when G1UseFixedWindowMMUTracker is enabled. _head_index = trim_index(_head_index + 1); assert(_head_index == _tail_index, "Because we have a full circular buffer"); _tail_index = trim_index(_tail_index + 1); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp index 1030454a741..dde9083a54c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp @@ -101,7 +101,7 @@ private: // If the array is full, an easy fix is to look for the pauses with // the shortest gap between them and consolidate them. // For now, we have taken the expedient alternative of forgetting - // the oldest entry in the event that +G1ForgetfulMMUTracker, thus + // the oldest entry in the event that +G1UseFixedWindowMMUTracker, thus // potentially violating MMU specs for some time thereafter. G1MMUTrackerQueueElem _array[QueueLength]; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index fa8916e52c5..a6839e36bfb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -467,7 +467,7 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, // and they are causing failures. When we resolve said race // conditions, we'll revert back to parallel remembered set // updating and scanning. See CRs 6677707 and 6677708. - if (G1ParallelRSetUpdatingEnabled || (worker_i == 0)) { + if (G1UseParallelRSetUpdating || (worker_i == 0)) { updateRS(worker_i); scanNewRefsRS(oc, worker_i); } else { @@ -476,7 +476,7 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, _g1p->record_update_rs_time(worker_i, 0.0); _g1p->record_scan_new_refs_time(worker_i, 0.0); } - if (G1ParallelRSetScanningEnabled || (worker_i == 0)) { + if (G1UseParallelRSetScanning || (worker_i == 0)) { scanRS(oc, worker_i); } else { _g1p->record_scan_rs_start_time(worker_i, os::elapsedTime() * 1000.0); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 7e084731a2d..9faf7ec1a70 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -70,7 +70,7 @@ develop(intx, G1PausesBtwnConcMark, -1, \ "If positive, fixed number of pauses between conc markings") \ \ - diagnostic(bool, G1SummarizeConcurrentMark, false, \ + diagnostic(bool, G1SummarizeConcMark, false, \ "Summarize concurrent mark info") \ \ diagnostic(bool, G1SummarizeRSetStats, false, \ @@ -85,7 +85,7 @@ diagnostic(bool, G1SummarizeZFStats, false, \ "Summarize zero-filling info") \ \ - diagnostic(bool, G1TraceConcurrentRefinement, false, \ + diagnostic(bool, G1TraceConcRefinement, false, \ "Trace G1 concurrent refinement") \ \ product(intx, G1MarkStackSize, 2 * 1024 * 1024, \ @@ -110,10 +110,10 @@ develop(bool, G1SATBBarrierPrintNullPreVals, false, \ "If true, count frac of ptr writes with null pre-vals.") \ \ - product(intx, G1SATBLogBufferSize, 1*K, \ + product(intx, G1SATBBufferSize, 1*K, \ "Number of entries in an SATB log buffer.") \ \ - product(intx, G1SATBProcessCompletedThreshold, 20, \ + develop(intx, G1SATBProcessCompletedThreshold, 20, \ "Number of completed buffers that triggers log processing.") \ \ develop(intx, G1ExtraRegionSurvRate, 33, \ @@ -127,7 +127,7 @@ develop(bool, G1SATBPrintStubs, false, \ "If true, print generated stubs for the SATB barrier") \ \ - product(intx, G1ExpandByPercentOfAvailable, 20, \ + experimental(intx, G1ExpandByPercentOfAvailable, 20, \ "When expanding, % of uncommitted space to claim.") \ \ develop(bool, G1RSBarrierRegionFilter, true, \ @@ -165,36 +165,36 @@ product(intx, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ \ - product(intx, G1ConcRefineYellowZone, 0, \ + product(intx, G1ConcRefinementYellowZone, 0, \ "Number of enqueued update buffers that will " \ "trigger concurrent processing. Will be selected ergonomically " \ "by default.") \ \ - product(intx, G1ConcRefineRedZone, 0, \ + product(intx, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ "Will be selected ergonomically by default. Zero will disable " \ "concurrent processing.") \ \ - product(intx, G1ConcRefineGreenZone, 0, \ + product(intx, G1ConcRefinementGreenZone, 0, \ "The number of update buffers that are left in the queue by the " \ "concurrent processing threads. Will be selected ergonomically " \ "by default.") \ \ - product(intx, G1ConcRefineServiceInterval, 300, \ + product(intx, G1ConcRefinementServiceIntervalMillis, 300, \ "The last concurrent refinement thread wakes up every " \ "specified number of milliseconds to do miscellaneous work.") \ \ - product(intx, G1ConcRefineThresholdStep, 0, \ + product(intx, G1ConcRefinementThresholdStep, 0, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ "Will be selected ergonomically by default.") \ \ - product(intx, G1RSUpdatePauseFractionPercent, 10, \ + product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ "process RS update buffers during the collection pause.") \ \ - product(bool, G1AdaptiveConcRefine, true, \ + product(bool, G1UseAdaptiveConcRefinement, true, \ "Select green, yellow and red zones adaptively to meet the " \ "the pause requirements.") \ \ @@ -245,15 +245,15 @@ "the number of regions for which we'll print a surv rate " \ "summary.") \ \ - product(bool, G1UseScanOnlyPrefix, false, \ + develop(bool, G1UseScanOnlyPrefix, false, \ "It determines whether the system will calculate an optimum " \ "scan-only set.") \ \ - product(intx, G1MinReservePercent, 10, \ + product(intx, G1ReservePercent, 10, \ "It determines the minimum reserve we should have in the heap " \ "to minimize the probability of promotion failure.") \ \ - diagnostic(bool, G1PrintRegions, false, \ + diagnostic(bool, G1PrintHeapRegions, false, \ "If set G1 will print information on which regions are being " \ "allocated and which are reclaimed.") \ \ @@ -263,9 +263,6 @@ develop(bool, G1HRRSFlushLogBuffersOnVerify, false, \ "Forces flushing of log buffers before verification.") \ \ - product(bool, G1UseSurvivorSpaces, true, \ - "When true, use survivor space.") \ - \ develop(bool, G1FailOnFPError, false, \ "When set, G1 will fail when it encounters an FP 'error', " \ "so as to allow debugging") \ @@ -280,21 +277,21 @@ "If non-0 is the size of the G1 survivor space, " \ "otherwise SurvivorRatio is used to determine the size") \ \ - product(bool, G1ForgetfulMMUTracker, false, \ + product(bool, G1UseFixedWindowMMUTracker, false, \ "If the MMU tracker's memory is full, forget the oldest entry") \ \ product(uintx, G1HeapRegionSize, 0, \ "Size of the G1 regions.") \ \ - experimental(bool, G1ParallelRSetUpdatingEnabled, false, \ + experimental(bool, G1UseParallelRSetUpdating, false, \ "Enables the parallelization of remembered set updating " \ "during evacuation pauses") \ \ - experimental(bool, G1ParallelRSetScanningEnabled, false, \ + experimental(bool, G1UseParallelRSetScanning, false, \ "Enables the parallelization of remembered set scanning " \ "during evacuation pauses") \ \ - product(uintx, G1ParallelRSetThreads, 0, \ + product(uintx, G1ConcRefinementThreads, 0, \ "If non-0 is the number of parallel rem set update threads, " \ "otherwise the value is determined ergonomically.") \ \ From 77b2dfce1dd9690be2f6949072589d0afca35325 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 23 Feb 2010 23:14:34 -0500 Subject: [PATCH 07/33] 6928073: G1: use existing command line parameters for marking cycle initiation Replace the combination of the G1SteadyStateUsed / G1SteadyStateUsedDelta parameteres to decide the marking initiation threshold and instead use InitiatingHeapOccupancyPercent. Reviewed-by: ysr, johnc --- .../vm/gc_implementation/g1/g1CollectorPolicy.cpp | 13 +------------ .../share/vm/gc_implementation/g1/g1_globals.hpp | 7 ------- hotspot/src/share/vm/runtime/arguments.cpp | 5 +++++ hotspot/src/share/vm/runtime/globals.hpp | 7 +++++++ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index ad5f37fa00a..63cf38ddd0f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -299,10 +299,6 @@ void G1CollectorPolicy::init() { assert(Heap_lock->owned_by_self(), "Locking discipline."); - if (G1SteadyStateUsed < 50) { - vm_exit_during_initialization("G1SteadyStateUsed must be at least 50%."); - } - initialize_gc_policy_counters(); if (G1Gen) { @@ -1425,7 +1421,7 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) { record_concurrent_mark_init_end_pre(0.0); size_t min_used_targ = - (_g1->capacity() / 100) * (G1SteadyStateUsed - G1SteadyStateUsedDelta); + (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; if (cur_used_bytes > min_used_targ) { if (cur_used_bytes <= _prev_collection_pause_used_at_end_bytes) { @@ -2618,13 +2614,6 @@ bool G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t word_size) { assert(_g1->regions_accounted_for(), "Region leakage!"); - // Initiate a pause when we reach the steady-state "used" target. - size_t used_hard = (_g1->capacity() / 100) * G1SteadyStateUsed; - size_t used_soft = - MAX2((_g1->capacity() / 100) * (G1SteadyStateUsed - G1SteadyStateUsedDelta), - used_hard/2); - size_t used = _g1->used(); - double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; size_t young_list_length = _g1->young_list_length(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 9faf7ec1a70..019f0de15cc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -100,13 +100,6 @@ develop(intx, G1ConcZFMaxRegions, 1, \ "Stop zero-filling when # of zf'd regions reaches") \ \ - product(intx, G1SteadyStateUsed, 90, \ - "If non-0, try to maintain 'used' at this pct (of max)") \ - \ - product(intx, G1SteadyStateUsedDelta, 30, \ - "If G1SteadyStateUsed is non-0, then do pause this number of " \ - "of percentage points earlier if no marking is in progress.") \ - \ develop(bool, G1SATBBarrierPrintNullPreVals, false, \ "If true, count frac of ptr writes with null pre-vals.") \ \ diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index f8e9a85abac..7862ccb88d1 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1737,6 +1737,11 @@ bool Arguments::check_vm_args_consistency() { status = false; } + if (UseG1GC) { + status = status && verify_percentage(InitiatingHeapOccupancyPercent, + "InitiatingHeapOccupancyPercent"); + } + status = status && verify_interval(RefDiscoveryPolicy, ReferenceProcessor::DiscoveryPolicyMin, ReferenceProcessor::DiscoveryPolicyMax, diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 833bd018c88..dca344d0225 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1724,6 +1724,13 @@ class CommandLineFlags { "Percentage CMS generation occupancy to start a CMS collection " \ "cycle. A negative value means that CMSTriggerRatio is used") \ \ + product(uintx, InitiatingHeapOccupancyPercent, 45, \ + "Percentage of the (entire) heap occupancy to start a " \ + "concurrent GC cycle. It us used by GCs that trigger a " \ + "concurrent GC cycle based on the occupancy of the entire heap, " \ + "not just one of the generations (e.g., G1). A value of 0 " \ + "denotes 'do constant GC cycles'.") \ + \ product(intx, CMSInitiatingPermOccupancyFraction, -1, \ "Percentage CMS perm generation occupancy to start a " \ "CMScollection cycle. A negative value means that " \ From f2547452281587f245cd5dfe1ef9010e4402dd89 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Wed, 24 Feb 2010 07:00:33 -0800 Subject: [PATCH 08/33] 6928081: G1: rename parameters common with CMS Rename marking stack sizing flags to be common between G1 and CMS Reviewed-by: ysr, tonyp --- .../cmsAdaptiveSizePolicy.cpp | 4 +- .../concurrentMarkSweepGeneration.cpp | 28 ++++---- .../gc_implementation/g1/concurrentMark.cpp | 12 ++-- .../vm/gc_implementation/g1/g1_globals.hpp | 3 - hotspot/src/share/vm/includeDB_core | 1 + hotspot/src/share/vm/runtime/arguments.cpp | 70 +++++++++++++++++++ hotspot/src/share/vm/runtime/arguments.hpp | 6 ++ hotspot/src/share/vm/runtime/globals.hpp | 15 ++-- hotspot/src/share/vm/utilities/taskqueue.hpp | 3 + 9 files changed, 108 insertions(+), 34 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp index a120f6af4ba..4a549c3498f 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp @@ -46,9 +46,9 @@ CMSAdaptiveSizePolicy::CMSAdaptiveSizePolicy(size_t init_eden_size, _processor_count = os::active_processor_count(); - if (CMSConcurrentMTEnabled && (ParallelCMSThreads > 1)) { + if (CMSConcurrentMTEnabled && (ConcGCThreads > 1)) { assert(_processor_count > 0, "Processor count is suspect"); - _concurrent_processor_count = MIN2((uint) ParallelCMSThreads, + _concurrent_processor_count = MIN2((uint) ConcGCThreads, (uint) _processor_count); } else { _concurrent_processor_count = 1; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 7cc33d105a4..863a31110e9 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -606,7 +606,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, assert(_modUnionTable.covers(_span), "_modUnionTable inconsistency?"); } - if (!_markStack.allocate(CMSMarkStackSize)) { + if (!_markStack.allocate(MarkStackSize)) { warning("Failed to allocate CMS Marking Stack"); return; } @@ -617,13 +617,13 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, // Support for multi-threaded concurrent phases if (ParallelGCThreads > 0 && CMSConcurrentMTEnabled) { - if (FLAG_IS_DEFAULT(ParallelCMSThreads)) { + if (FLAG_IS_DEFAULT(ConcGCThreads)) { // just for now - FLAG_SET_DEFAULT(ParallelCMSThreads, (ParallelGCThreads + 3)/4); + FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4); } - if (ParallelCMSThreads > 1) { + if (ConcGCThreads > 1) { _conc_workers = new YieldingFlexibleWorkGang("Parallel CMS Threads", - ParallelCMSThreads, true); + ConcGCThreads, true); if (_conc_workers == NULL) { warning("GC/CMS: _conc_workers allocation failure: " "forcing -CMSConcurrentMTEnabled"); @@ -634,13 +634,13 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, } } if (!CMSConcurrentMTEnabled) { - ParallelCMSThreads = 0; + ConcGCThreads = 0; } else { // Turn off CMSCleanOnEnter optimization temporarily for // the MT case where it's not fixed yet; see 6178663. CMSCleanOnEnter = false; } - assert((_conc_workers != NULL) == (ParallelCMSThreads > 1), + assert((_conc_workers != NULL) == (ConcGCThreads > 1), "Inconsistency"); // Parallel task queues; these are shared for the @@ -648,7 +648,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, // are not shared with parallel scavenge (ParNew). { uint i; - uint num_queues = (uint) MAX2(ParallelGCThreads, ParallelCMSThreads); + uint num_queues = (uint) MAX2(ParallelGCThreads, ConcGCThreads); if ((CMSParallelRemarkEnabled || CMSConcurrentMTEnabled || ParallelRefProcEnabled) @@ -3657,7 +3657,7 @@ bool CMSCollector::markFromRootsWork(bool asynch) { assert(_revisitStack.isEmpty(), "tabula rasa"); DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());) bool result = false; - if (CMSConcurrentMTEnabled && ParallelCMSThreads > 0) { + if (CMSConcurrentMTEnabled && ConcGCThreads > 0) { result = do_marking_mt(asynch); } else { result = do_marking_st(asynch); @@ -4174,10 +4174,10 @@ void CMSConcMarkingTask::coordinator_yield() { } bool CMSCollector::do_marking_mt(bool asynch) { - assert(ParallelCMSThreads > 0 && conc_workers() != NULL, "precondition"); + assert(ConcGCThreads > 0 && conc_workers() != NULL, "precondition"); // In the future this would be determined ergonomically, based // on #cpu's, # active mutator threads (and load), and mutation rate. - int num_workers = ParallelCMSThreads; + int num_workers = ConcGCThreads; CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace(); CompactibleFreeListSpace* perm_space = _permGen->cmsSpace(); @@ -6429,8 +6429,8 @@ bool CMSMarkStack::allocate(size_t size) { // For now we take the expedient path of just disabling the // messages for the problematic case.) void CMSMarkStack::expand() { - assert(_capacity <= CMSMarkStackSizeMax, "stack bigger than permitted"); - if (_capacity == CMSMarkStackSizeMax) { + assert(_capacity <= MarkStackSizeMax, "stack bigger than permitted"); + if (_capacity == MarkStackSizeMax) { if (_hit_limit++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) { // We print a warning message only once per CMS cycle. gclog_or_tty->print_cr(" (benign) Hit CMSMarkStack max size limit"); @@ -6438,7 +6438,7 @@ void CMSMarkStack::expand() { return; } // Double capacity if possible - size_t new_capacity = MIN2(_capacity*2, CMSMarkStackSizeMax); + size_t new_capacity = MIN2(_capacity*2, MarkStackSizeMax); // Do not give up existing stack until we have managed to // get the double capacity that we desired. ReservedSpace rs(ReservedSpace::allocation_align_size_up( diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 41966bed1d5..6a8fd95c2ba 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -447,7 +447,7 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, gclog_or_tty->print_cr("[global] init, heap start = "PTR_FORMAT", " "heap end = "PTR_FORMAT, _heap_start, _heap_end); - _markStack.allocate(G1MarkStackSize); + _markStack.allocate(MarkStackSize); _regionStack.allocate(G1MarkRegionStackSize); // Create & start a ConcurrentMark thread. @@ -483,8 +483,8 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, _accum_task_vtime[i] = 0.0; } - if (ParallelMarkingThreads > ParallelGCThreads) { - vm_exit_during_initialization("Can't have more ParallelMarkingThreads " + if (ConcGCThreads > ParallelGCThreads) { + vm_exit_during_initialization("Can't have more ConcGCThreads " "than ParallelGCThreads."); } if (ParallelGCThreads == 0) { @@ -494,11 +494,11 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ParallelMarkingThreads > 0) { - // notice that ParallelMarkingThreads overwrites G1MarkingOverheadPercent + if (ConcGCThreads > 0) { + // notice that ConcGCThreads overwrites G1MarkingOverheadPercent // if both are set - _parallel_marking_threads = ParallelMarkingThreads; + _parallel_marking_threads = ConcGCThreads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 019f0de15cc..45c4da0f8ec 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -88,9 +88,6 @@ diagnostic(bool, G1TraceConcRefinement, false, \ "Trace G1 concurrent refinement") \ \ - product(intx, G1MarkStackSize, 2 * 1024 * 1024, \ - "Size of the mark stack for concurrent marking.") \ - \ product(intx, G1MarkRegionStackSize, 1024 * 1024, \ "Size of the region stack for concurrent marking.") \ \ diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 0d1b52513e3..c8a5f616734 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -176,6 +176,7 @@ arguments.cpp management.hpp arguments.cpp oop.inline.hpp arguments.cpp os_.inline.hpp arguments.cpp referenceProcessor.hpp +arguments.cpp taskqueue.hpp arguments.cpp universe.inline.hpp arguments.cpp vm_version_.hpp diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 7862ccb88d1..11a6320463a 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1203,6 +1203,11 @@ void Arguments::set_cms_and_parnew_gc_flags() { if (!FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim) || !FLAG_IS_DEFAULT(OldPLABWeight)) { CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight); } + if (PrintGCDetails && Verbose) { + tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk", + MarkStackSize / K, MarkStackSizeMax / K); + tty->print_cr("ConcGCThreads: %u", ConcGCThreads); + } } #endif // KERNEL @@ -1339,6 +1344,17 @@ void Arguments::set_g1_gc_flags() { if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) { FLAG_SET_DEFAULT(MaxGCPauseMillis, 200); } + + if (FLAG_IS_DEFAULT(MarkStackSize)) { + // Size as a multiple of TaskQueueSuper::N which is larger + // for 64-bit. + FLAG_SET_DEFAULT(MarkStackSize, 128 * TaskQueueSuper::total_size()); + } + if (PrintGCDetails && Verbose) { + tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk", + MarkStackSize / K, MarkStackSizeMax / K); + tty->print_cr("ConcGCThreads: %u", ConcGCThreads); + } } void Arguments::set_heap_size() { @@ -1800,6 +1816,29 @@ static bool match_option(const JavaVMOption* option, const char** names, const c return false; } +bool Arguments::parse_uintx(const char* value, + uintx* uintx_arg, + uintx min_size) { + + // Check the sign first since atomull() parses only unsigned values. + bool value_is_positive = !(*value == '-'); + + if (value_is_positive) { + julong n; + bool good_return = atomull(value, &n); + if (good_return) { + bool above_minimum = n >= min_size; + bool value_is_too_large = n > max_uintx; + + if (above_minimum && !value_is_too_large) { + *uintx_arg = n; + return true; + } + } + } + return false; +} + Arguments::ArgsRange Arguments::parse_memory_size(const char* s, julong* long_arg, julong min_size) { @@ -2458,6 +2497,37 @@ SOLARIS_ONLY( jio_fprintf(defaultStream::error_stream(), "Please use -XX:YoungPLABSize in place of " "-XX:ParallelGCToSpaceAllocBufferSize in the future\n"); + } else if (match_option(option, "-XX:CMSMarkStackSize=", &tail) || + match_option(option, "-XX:G1MarkStackSize=", &tail)) { + julong stack_size = 0; + ArgsRange errcode = parse_memory_size(tail, &stack_size, 1); + if (errcode != arg_in_range) { + jio_fprintf(defaultStream::error_stream(), + "Invalid mark stack size: %s\n", option->optionString); + describe_range_error(errcode); + return JNI_EINVAL; + } + FLAG_SET_CMDLINE(uintx, MarkStackSize, stack_size); + } else if (match_option(option, "-XX:CMSMarkStackSizeMax=", &tail)) { + julong max_stack_size = 0; + ArgsRange errcode = parse_memory_size(tail, &max_stack_size, 1); + if (errcode != arg_in_range) { + jio_fprintf(defaultStream::error_stream(), + "Invalid maximum mark stack size: %s\n", + option->optionString); + describe_range_error(errcode); + return JNI_EINVAL; + } + FLAG_SET_CMDLINE(uintx, MarkStackSizeMax, max_stack_size); + } else if (match_option(option, "-XX:ParallelMarkingThreads=", &tail) || + match_option(option, "-XX:ParallelCMSThreads=", &tail)) { + uintx conc_threads = 0; + if (!parse_uintx(tail, &conc_threads, 1)) { + jio_fprintf(defaultStream::error_stream(), + "Invalid concurrent threads: %s\n", option->optionString); + return JNI_EINVAL; + } + FLAG_SET_CMDLINE(uintx, ConcGCThreads, conc_threads); } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx // Skip -XX:Flags= since that case has already been handled if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) { diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 2747c2d5035..17382d8b664 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -343,6 +343,12 @@ class Arguments : AllStatic { static ArgsRange check_memory_size(julong size, julong min_size); static ArgsRange parse_memory_size(const char* s, julong* long_arg, julong min_size); + // Parse a string for a unsigned integer. Returns true if value + // is an unsigned integer greater than or equal to the minimum + // parameter passed and returns the value in uintx_arg. Returns + // false otherwise, with uintx_arg undefined. + static bool parse_uintx(const char* value, uintx* uintx_arg, + uintx min_size); // methods to build strings from individual args static void build_jvm_args(const char* arg); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index dca344d0225..96b66b1b759 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1245,9 +1245,6 @@ class CommandLineFlags { product(uintx, ParallelGCThreads, 0, \ "Number of parallel threads parallel gc will use") \ \ - product(uintx, ParallelCMSThreads, 0, \ - "Max number of threads CMS will use for concurrent work") \ - \ develop(bool, ParallelOldGCSplitALot, false, \ "Provoke splitting (copying data from a young gen space to" \ "multiple destination spaces)") \ @@ -1258,8 +1255,8 @@ class CommandLineFlags { develop(bool, TraceRegionTasksQueuing, false, \ "Trace the queuing of the region tasks") \ \ - product(uintx, ParallelMarkingThreads, 0, \ - "Number of marking threads concurrent gc will use") \ + product(uintx, ConcGCThreads, 0, \ + "Number of threads concurrent gc will use") \ \ product(uintx, YoungPLABSize, 4096, \ "Size of young gen promotion labs (in HeapWords)") \ @@ -1535,11 +1532,11 @@ class CommandLineFlags { develop(bool, CMSOverflowEarlyRestoration, false, \ "Whether preserved marks should be restored early") \ \ - product(uintx, CMSMarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \ - "Size of CMS marking stack") \ + product(uintx, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \ + "Size of marking stack") \ \ - product(uintx, CMSMarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \ - "Max size of CMS marking stack") \ + product(uintx, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \ + "Max size of marking stack") \ \ notproduct(bool, CMSMarkStackOverflowALot, false, \ "Whether we should simulate frequent marking stack / work queue" \ diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index 19bdb3245c4..5376bc09f3d 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -133,6 +133,9 @@ public: // Maximum number of elements allowed in the queue. This is two less // than the actual queue size, for somewhat complicated reasons. uint max_elems() { return N - 2; } + + // Total size of queue. + static const uint total_size() { return N; } }; template class GenericTaskQueue: public TaskQueueSuper { From 1eb12e87a700ee292ed0b88bdaa8fa9c35753c14 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 24 Feb 2010 14:56:20 -0500 Subject: [PATCH 09/33] 6928065: G1: use existing command line parameters to set the young generation size See synopsis Reviewed-by: johnc, jmasa --- .../g1/g1CollectorPolicy.cpp | 36 +++++++++++++++++-- .../vm/gc_implementation/g1/g1_globals.hpp | 3 -- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 63cf38ddd0f..32d707a281e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -292,10 +292,37 @@ void G1CollectorPolicy::initialize_flags() { CollectorPolicy::initialize_flags(); } +// The easiest way to deal with the parsing of the NewSize / +// MaxNewSize / etc. parameteres is to re-use the code in the +// TwoGenerationCollectorPolicy class. This is similar to what +// ParallelScavenge does with its GenerationSizer class (see +// ParallelScavengeHeap::initialize()). We might change this in the +// future, but it's a good start. +class G1YoungGenSizer : public TwoGenerationCollectorPolicy { + size_t size_to_region_num(size_t byte_size) { + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); + } + +public: + G1YoungGenSizer() { + initialize_flags(); + initialize_size_info(); + } + + size_t min_young_region_num() { + return size_to_region_num(_min_gen0_size); + } + size_t initial_young_region_num() { + return size_to_region_num(_initial_gen0_size); + } + size_t max_young_region_num() { + return size_to_region_num(_max_gen0_size); + } +}; + void G1CollectorPolicy::init() { // Set aside an initial future to_space. _g1 = G1CollectedHeap::heap(); - size_t regions = Universe::heap()->capacity() / HeapRegion::GrainBytes; assert(Heap_lock->owned_by_self(), "Locking discipline."); @@ -304,12 +331,15 @@ void G1CollectorPolicy::init() { if (G1Gen) { _in_young_gc_mode = true; - if (G1YoungGenSize == 0) { + G1YoungGenSizer sizer; + size_t initial_region_num = sizer.initial_young_region_num(); + + if (UseAdaptiveSizePolicy) { set_adaptive_young_list_length(true); _young_list_fixed_length = 0; } else { set_adaptive_young_list_length(false); - _young_list_fixed_length = (G1YoungGenSize / HeapRegion::GrainBytes); + _young_list_fixed_length = initial_region_num; } _free_regions_at_end_of_collection = _g1->free_regions(); _scan_only_regions_at_end_of_collection = 0; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 45c4da0f8ec..d2363ad6705 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -37,9 +37,6 @@ develop(intx, G1MarkingOverheadPercent, 0, \ "Overhead of concurrent marking") \ \ - product(uintx, G1YoungGenSize, 0, \ - "Size of the G1 young generation, 0 is the adaptive policy") \ - \ develop(bool, G1Gen, true, \ "If true, it will enable the generational G1") \ \ From 0ab4fb9e379ee1e6976b58b725a245994bade963 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 25 Feb 2010 11:38:50 -0800 Subject: [PATCH 10/33] 6915557: assert(_gvn.type(l)->higher_equal(type),"must constrain OSR typestate") with debug build Reviewed-by: kvn --- hotspot/src/share/vm/opto/parse1.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 4cae42dd2cc..edac19b6bf3 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,7 +237,6 @@ void Parse::load_interpreter_state(Node* osr_buf) { C->record_method_not_compilable("OSR in empty or breakpointed method"); return; } - MethodLivenessResult raw_live_locals = method()->raw_liveness_at_bci(osr_bci()); // Extract the needed locals from the interpreter frame. Node *locals_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals-1)*wordSize); @@ -306,6 +305,7 @@ void Parse::load_interpreter_state(Node* osr_buf) { SafePointNode* bad_type_exit = clone_map(); bad_type_exit->set_control(new (C, 1) RegionNode(1)); + assert(osr_block->flow()->jsrs()->size() == 0, "should be no jsrs live at osr point"); for (index = 0; index < max_locals; index++) { if (stopped()) break; Node* l = local(index); @@ -317,8 +317,18 @@ void Parse::load_interpreter_state(Node* osr_buf) { continue; } } - if (type->basic_type() == T_ADDRESS && !raw_live_locals.at(index)) { - // Skip type check for dead address locals + if (type->basic_type() == T_ADDRESS) { + // 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. continue; } set_local(index, check_interpreter_type(l, type, bad_type_exit)); From 8554996b9b1b1c7095c191358e55b7c27c5c071d Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 25 Feb 2010 15:55:47 -0800 Subject: [PATCH 11/33] 6930035: C2 type system incorrectly handles case j.l.Object->meet(constant AryPtr) Add missing code. Reviewed-by: never --- hotspot/src/share/vm/opto/type.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 289835af4c8..ba1cf3aa12b 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2809,7 +2809,8 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { // then we can subclass in the Java class hierarchy. if (klass()->equals(ciEnv::current()->Object_klass())) { // that is, tp's array type is a subtype of my klass - return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id); + return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), + tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id); } } // The other case cannot happen, since I cannot be a subtype of an array. @@ -3415,7 +3416,8 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { // then we can subclass in the Java class hierarchy. if( tp->klass()->equals(ciEnv::current()->Object_klass()) ) { // that is, my array type is a subtype of 'tp' klass - return make( ptr, _ary, _klass, _klass_is_exact, offset, instance_id ); + return make( ptr, (ptr == Constant ? const_oop() : NULL), + _ary, _klass, _klass_is_exact, offset, instance_id ); } } // The other case cannot happen, since t cannot be a subtype of an array. From 667e7ff0c059fd7c587f2261f605d13272cb540a Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 25 Feb 2010 22:58:43 -0800 Subject: [PATCH 12/33] 6930116: loop predication code does not handle If nodes with only one projection Add check for iff->outcnt() < 2. Reviewed-by: never --- hotspot/src/share/vm/opto/loopTransform.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 0fa5a4086a0..daa3ceca869 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1785,6 +1785,8 @@ bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_pred bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reason_predicate) { Node *in0 = proj->in(0); if (!in0->is_If()) return false; + // Variation of a dead If node. + if (in0->outcnt() < 2) return false; IfNode* iff = in0->as_If(); // we need "If(Conv2B(Opaque1(...)))" pattern for must_reason_predicate From cef423370c08d1909a4a5e2f24e5537bb78e6bcb Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Fri, 26 Feb 2010 16:40:55 -0500 Subject: [PATCH 13/33] 6923123: Hotspot refuses to start when -Xmx4m or -Xms4m is specified Reduce NewSize from 4m to 1m. Reviewed-by: tonyp, jmasa --- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 833bd018c88..cf04eddaf26 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2925,7 +2925,7 @@ class CommandLineFlags { product(uintx, OldSize, ScaleForWordSize(4*M), \ "Initial tenured generation size (in bytes)") \ \ - product(uintx, NewSize, ScaleForWordSize(4*M), \ + product(uintx, NewSize, ScaleForWordSize(1*M), \ "Initial new generation size (in bytes)") \ \ product(uintx, MaxNewSize, max_uintx, \ From e904069b514ec525d34ce99d8b94e258486a09ff Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 1 Mar 2010 12:12:35 -0800 Subject: [PATCH 14/33] 6930398: fix for return address locals in OSR entries uses wrong test Reviewed-by: kvn --- hotspot/src/share/vm/opto/parse1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index edac19b6bf3..5543292ef30 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -317,7 +317,7 @@ void Parse::load_interpreter_state(Node* osr_buf) { continue; } } - if (type->basic_type() == T_ADDRESS) { + if (osr_block->flow()->local_type_at(index)->is_return_address()) { // 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 From 13ac3be829a6aa6612bfbcc69090a071cb674b59 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 2 Mar 2010 12:09:40 -0800 Subject: [PATCH 15/33] 6914050: jvm assertion "guard pages must be in use" in -Xcomp mode Move creating stack guard pages in jni attach thread before potential java call rather than after. Also cleanup stack guard pages when jni attach fails Reviewed-by: never, dholmes --- hotspot/src/share/vm/prims/jni.cpp | 7 ++++--- hotspot/src/share/vm/runtime/thread.cpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index fbf66099a79..1cbfa61a17a 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3401,12 +3401,16 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae thread->set_thread_state(_thread_in_vm); // Must do this before initialize_thread_local_storage thread->record_stack_base_and_size(); + thread->initialize_thread_local_storage(); if (!os::create_attached_thread(thread)) { delete thread; return JNI_ERR; } + // Enable stack overflow checks + thread->create_stack_guard_pages(); + thread->initialize_tlab(); // Crucial that we do not have a safepoint check for this thread, since it has @@ -3452,9 +3456,6 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae // to regrab the threads_lock thread->set_attached(); - // Enable stack overflow checks - thread->create_stack_guard_pages(); - // Set java thread status. java_lang_Thread::set_thread_status(thread->threadObj(), java_lang_Thread::RUNNABLE); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 3bdf8dad0f1..e05be5e4103 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1637,6 +1637,9 @@ void JavaThread::cleanup_failed_attach_current_thread() { JNIHandleBlock::release_block(block); } + // These have to be removed while this is still a valid thread. + remove_stack_guard_pages(); + if (UseTLAB) { tlab().make_parsable(true); // retire TLAB, if any } From 5fdec09798d70e71e2ed6705a590fa38e00ff63c Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Wed, 3 Mar 2010 08:10:41 -0800 Subject: [PATCH 16/33] 6910182: CMS: assert(_cursor[j] == _survivor_plab_array[j].end(),"Ctl pt invariant") Calculation of the slicing of survivor spaces for MT was incorrect. Reviewed-by: ysr --- .../concurrentMarkSweep/concurrentMarkSweepGeneration.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 863a31110e9..9ed32074822 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -723,8 +723,9 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, // Support for parallelizing survivor space rescan if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) { - size_t max_plab_samples = cp->max_gen0_size()/ - ((SurvivorRatio+2)*MinTLABSize); + const size_t max_plab_samples = + ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize; + _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads); _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples); _cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads); From 94a808f51d4ca1c5d328f67eeaa793f80052c87c Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 8 Mar 2010 04:46:30 -0800 Subject: [PATCH 17/33] 6932536: JSR 292 modified JDK MethodHandlesTest fails on x86_64 A modified MethodHandlesTest revealed two bugs on x86_64. Reviewed-by: never, jrose --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index fa3c5043246..5e168c82bdf 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -715,9 +715,14 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan switch (ek) { case _adapter_opt_i2l: { +#ifdef _LP64 + __ movslq(rdx_temp, vmarg1); // Load sign-extended + __ movq(vmarg1, rdx_temp); // Store into first slot +#else __ movl(rdx_temp, vmarg1); - __ sarl(rdx_temp, 31); // __ extend_sign() + __ sarl(rdx_temp, BitsPerInt - 1); // __ extend_sign() __ movl(vmarg2, rdx_temp); // store second word +#endif } break; case _adapter_opt_unboxl: @@ -727,10 +732,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG); assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), ""); __ null_check(rdx_temp, value_offset); +#ifdef _LP64 + __ movq(rbx_temp, Address(rdx_temp, value_offset)); + __ movq(vmarg1, rbx_temp); +#else __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt)); __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt)); __ movl(vmarg1, rbx_temp); __ movl(vmarg2, rdx_temp); +#endif } break; default: @@ -925,8 +935,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // 'stack_move' is negative number of words to duplicate Register rdx_stack_move = rdx_temp; - __ movl(rdx_stack_move, rcx_amh_conversion); - __ sarl(rdx_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdx_stack_move, rcx_amh_conversion); + __ sarptr(rdx_stack_move, CONV_STACK_MOVE_SHIFT); int argslot0_num = 0; Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num)); @@ -988,8 +998,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // 'stack_move' is number of words to drop Register rdi_stack_move = rdi; - __ movl(rdi_stack_move, rcx_amh_conversion); - __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdi_stack_move, rcx_amh_conversion); + __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); remove_arg_slots(_masm, rdi_stack_move, rax_argslot, rbx_temp, rdx_temp); @@ -1079,8 +1089,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize())); // 'stack_move' is negative number of words to insert Register rdi_stack_move = rdi; - __ movl(rdi_stack_move, rcx_amh_conversion); - __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdi_stack_move, rcx_amh_conversion); + __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); Register rsi_temp = rsi_array; // spill this insert_arg_slots(_masm, rdi_stack_move, -1, rax_argslot, rbx_temp, rsi_temp); From 11051a4e6a0b9065a526f71600c2abd279bf824d Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 9 Mar 2010 11:02:39 -0800 Subject: [PATCH 18/33] 6932270: Allow Java's ELF symtab reader to use separate debuginfo files Reviewed-by: never --- hotspot/agent/src/os/linux/libproc_impl.c | 2 +- hotspot/agent/src/os/linux/symtab.c | 324 +++++++++++++++++- hotspot/agent/src/os/linux/symtab.h | 2 +- hotspot/make/linux/makefiles/build_vm_def.sh | 5 + .../make/linux/makefiles/mapfile-vers-debug | 3 + .../make/linux/makefiles/mapfile-vers-product | 3 + hotspot/make/linux/makefiles/vm.make | 11 +- 7 files changed, 342 insertions(+), 8 deletions(-) create mode 100644 hotspot/make/linux/makefiles/build_vm_def.sh diff --git a/hotspot/agent/src/os/linux/libproc_impl.c b/hotspot/agent/src/os/linux/libproc_impl.c index be00178f22f..ace53bcc37f 100644 --- a/hotspot/agent/src/os/linux/libproc_impl.c +++ b/hotspot/agent/src/os/linux/libproc_impl.c @@ -174,7 +174,7 @@ lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, return NULL; } - newlib->symtab = build_symtab(newlib->fd); + newlib->symtab = build_symtab(newlib->fd, libname); if (newlib->symtab == NULL) { print_debug("symbol table build failed for %s\n", newlib->name); } diff --git a/hotspot/agent/src/os/linux/symtab.c b/hotspot/agent/src/os/linux/symtab.c index ec3b99ff326..d135a333326 100644 --- a/hotspot/agent/src/os/linux/symtab.c +++ b/hotspot/agent/src/os/linux/symtab.c @@ -53,8 +53,274 @@ typedef struct symtab { struct hsearch_data *hash_table; } symtab_t; -// read symbol table from given fd. -struct symtab* build_symtab(int fd) { + +// Directory that contains global debuginfo files. In theory it +// should be possible to change this, but in a Java environment there +// is no obvious place to put a user interface to do it. Maybe this +// could be set with an environment variable. +static const char debug_file_directory[] = "/usr/lib/debug"; + +/* The CRC used in gnu_debuglink, retrieved from + http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files. */ +unsigned int gnu_debuglink_crc32 (unsigned int crc, + unsigned char *buf, size_t len) +{ + static const unsigned int crc32_table[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; + unsigned char *end; + + crc = ~crc & 0xffffffff; + for (end = buf + len; buf < end; ++buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc & 0xffffffff; +} + +/* Open a debuginfo file and check its CRC. If it exists and the CRC + matches return its fd. */ +static int +open_debug_file (const char *pathname, unsigned int crc) +{ + unsigned int file_crc = 0; + unsigned char buffer[8 * 1024]; + + int fd = pathmap_open(pathname); + + if (fd < 0) + return -1; + + lseek(fd, 0, SEEK_SET); + + for (;;) { + int len = read(fd, buffer, sizeof buffer); + if (len <= 0) + break; + file_crc = gnu_debuglink_crc32(file_crc, buffer, len); + } + + if (crc == file_crc) + return fd; + else { + close(fd); + return -1; + } +} + +/* Find an ELF section. */ +static struct elf_section *find_section_by_name(char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + ELF_SHDR* cursct = NULL; + char *strtab; + int cnt; + + if (scn_cache[ehdr->e_shstrndx].c_data == NULL) { + if ((scn_cache[ehdr->e_shstrndx].c_data + = read_section_data(fd, ehdr, cursct)) == NULL) { + return NULL; + } + } + + strtab = scn_cache[ehdr->e_shstrndx].c_data; + + for (cursct = shbuf, cnt = 0; + cnt < ehdr->e_shnum; + cnt++, cursct++) { + if (strcmp(cursct->sh_name + strtab, name) == 0) { + scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct); + return &scn_cache[cnt]; + } + } + + return NULL; +} + +/* Look for a ".gnu_debuglink" section. If one exists, try to open a + suitable debuginfo file. */ +static int open_file_from_debug_link(const char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + int debug_fd; + struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr, + shbuf, scn_cache); + if (debug_link == NULL) + return -1; + char *debug_filename = debug_link->c_data; + int offset = (strlen(debug_filename) + 4) >> 2; + static unsigned int crc; + crc = ((unsigned int*)debug_link->c_data)[offset]; + char *debug_pathname = malloc(strlen(debug_filename) + + strlen(name) + + strlen(".debug/") + + strlen(debug_file_directory) + + 2); + strcpy(debug_pathname, name); + char *last_slash = strrchr(debug_pathname, '/'); + if (last_slash == NULL) + return -1; + + /* Look in the same directory as the object. */ + strcpy(last_slash+1, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + /* Look in a subdirectory named ".debug". */ + strcpy(last_slash+1, ".debug/"); + strcat(last_slash, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + /* Look in /usr/lib/debug + the full pathname. */ + strcpy(debug_pathname, debug_file_directory); + strcat(debug_pathname, name); + last_slash = strrchr(debug_pathname, '/'); + strcpy(last_slash+1, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + free(debug_pathname); + return -1; +} + +static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo); + +/* Look for a ".gnu_debuglink" section. If one exists, try to open a + suitable debuginfo file and read a symbol table from it. */ +static struct symtab *build_symtab_from_debug_link(const char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache); + + if (fd >= 0) { + struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); + close(fd); + return symtab; + } + + return NULL; +} + +// Given a build_id, find the associated debuginfo file +static char * +build_id_to_debug_filename (size_t size, unsigned char *data) +{ + char *filename, *s; + + filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 + + 2 * size + (sizeof ".debug" - 1) + 1); + s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory); + if (size > 0) + { + size--; + s += sprintf (s, "%02x", *data++); + } + if (size > 0) + *s++ = '/'; + while (size-- > 0) + s += sprintf (s, "%02x", *data++); + strcpy (s, ".debug"); + + return filename; +} + +// Read a build ID note. Try to open any associated debuginfo file +// and return its symtab +static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note) +{ + int fd; + struct symtab *symtab = NULL; + + unsigned char *bytes + = (unsigned char*)(note+1) + note->n_namesz; + unsigned char *filename + = (build_id_to_debug_filename (note->n_descsz, bytes)); + + fd = pathmap_open(filename); + if (fd >= 0) { + symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); + close(fd); + } + free(filename); + + return symtab; +} + +// read symbol table from given fd. If try_debuginfo) is true, also +// try to open an associated debuginfo file +static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) { ELF_EHDR ehdr; char *names = NULL; struct symtab* symtab = NULL; @@ -66,6 +332,7 @@ struct symtab* build_symtab(int fd) { ELF_SHDR* cursct = NULL; ELF_PHDR* phbuf = NULL; ELF_PHDR* phdr = NULL; + int sym_section = SHT_DYNSYM; uintptr_t baseaddr = (uintptr_t)-1; @@ -90,18 +357,23 @@ struct symtab* build_symtab(int fd) { for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { scn_cache[cnt].c_shdr = cursct; - if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB) { + if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB + || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) { if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { goto quit; } } + if (cursct->sh_type == SHT_SYMTAB) { + // Full symbol table available so use that + sym_section = cursct->sh_type; + } cursct++; } for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { ELF_SHDR *shdr = scn_cache[cnt].c_shdr; - if (shdr->sh_type == SHT_SYMTAB) { + if (shdr->sh_type == sym_section) { ELF_SYM *syms; int j, n, rslt; size_t size; @@ -163,6 +435,45 @@ struct symtab* build_symtab(int fd) { } } + // Look for a separate debuginfo file. + if (try_debuginfo) { + + // We prefer a debug symtab to an object's own symtab, so look in + // the debuginfo file. We stash a copy of the old symtab in case + // there is no debuginfo. + struct symtab* prev_symtab = symtab; + symtab = NULL; + +#ifdef NT_GNU_BUILD_ID + // First we look for a Build ID + for (cursct = shbuf, cnt = 0; + symtab == NULL && cnt < ehdr.e_shnum; + cnt++) { + if (cursct->sh_type == SHT_NOTE) { + Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data; + if (note->n_type == NT_GNU_BUILD_ID) { + symtab = build_symtab_from_build_id(note); + } + } + cursct++; + } +#endif + + // Then, if that doesn't work, the debug link + if (symtab == NULL) { + symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf, + scn_cache); + } + + // If we still haven't found a symtab, use the object's own symtab. + if (symtab != NULL) { + if (prev_symtab != NULL) + destroy_symtab(prev_symtab); + } else { + symtab = prev_symtab; + } + } + quit: if (shbuf) free(shbuf); if (phbuf) free(phbuf); @@ -177,6 +488,11 @@ quit: return symtab; } +struct symtab* build_symtab(int fd, const char *filename) { + return build_symtab_internal(fd, filename, /* try_debuginfo */ true); +} + + void destroy_symtab(struct symtab* symtab) { if (!symtab) return; if (symtab->strs) free(symtab->strs); diff --git a/hotspot/agent/src/os/linux/symtab.h b/hotspot/agent/src/os/linux/symtab.h index 371fc7fb166..90762cb66e1 100644 --- a/hotspot/agent/src/os/linux/symtab.h +++ b/hotspot/agent/src/os/linux/symtab.h @@ -32,7 +32,7 @@ struct symtab; // build symbol table for a given ELF file descriptor -struct symtab* build_symtab(int fd); +struct symtab* build_symtab(int fd, const char *filename); // destroy the symbol table void destroy_symtab(struct symtab* symtab); diff --git a/hotspot/make/linux/makefiles/build_vm_def.sh b/hotspot/make/linux/makefiles/build_vm_def.sh new file mode 100644 index 00000000000..51a07b9bfa2 --- /dev/null +++ b/hotspot/make/linux/makefiles/build_vm_def.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +nm --defined-only $* | awk ' + { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" } + ' diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 65765b2963d..26feea941d5 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -290,6 +290,9 @@ SUNWprivate_1.1 { # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; }; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 884cbd04528..9ffae3e7bcc 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -285,6 +285,9 @@ SUNWprivate_1.1 { # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; }; diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index fb847e31922..1506811cdb3 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -121,14 +121,21 @@ JVM_OBJ_FILES = $(Obj_Files) vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) -mapfile : $(MAPFILE) +mapfile : $(MAPFILE) vm.def rm -f $@ - cat $^ > $@ + awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \ + { system ("cat vm.def"); } \ + else \ + { print $$0 } \ + }' > $@ < $(MAPFILE) mapfile_reorder : mapfile $(REORDERFILE) rm -f $@ cat $^ > $@ +vm.def: $(Res_Files) $(Obj_Files) + sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@ + ifeq ($(ZERO_LIBARCH), ppc64) STATIC_CXX = false else From ffec4c00c4b91cfea128c26beca494f0af92463a Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 9 Mar 2010 20:16:19 +0100 Subject: [PATCH 19/33] 6919934: JSR 292 needs to support x86 C1 This implements JSR 292 support for C1 x86. Reviewed-by: never, jrose, kvn --- .../src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp | 12 ++- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 35 +++++---- .../cpu/sparc/vm/c1_MacroAssembler_sparc.cpp | 13 +--- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 26 ++----- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 5 +- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 4 +- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 2 +- .../sparc/vm/templateInterpreter_sparc.cpp | 4 +- hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp | 10 ++- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 70 ++++++++--------- .../src/cpu/x86/vm/c1_MacroAssembler_x86.cpp | 18 ++--- hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 76 +++++++------------ .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 45 +++++++---- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 2 +- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 50 ++++++------ .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 2 +- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 16 ++-- hotspot/src/share/vm/c1/c1_CodeStubs.hpp | 24 +++++- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 53 +++++++------ hotspot/src/share/vm/c1/c1_IR.cpp | 6 +- hotspot/src/share/vm/c1/c1_IR.hpp | 7 +- hotspot/src/share/vm/c1/c1_Instruction.cpp | 15 +++- hotspot/src/share/vm/c1/c1_Instruction.hpp | 22 ++++-- hotspot/src/share/vm/c1/c1_LIR.cpp | 10 ++- hotspot/src/share/vm/c1/c1_LIR.hpp | 15 ++++ hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 26 +++++-- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 11 ++- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 51 ++++++++++++- hotspot/src/share/vm/c1/c1_MacroAssembler.hpp | 4 +- hotspot/src/share/vm/ci/ciCPCache.cpp | 12 ++- hotspot/src/share/vm/ci/ciCPCache.hpp | 4 +- hotspot/src/share/vm/includeDB_compiler1 | 3 +- hotspot/src/share/vm/includeDB_core | 1 + hotspot/src/share/vm/opto/runtime.cpp | 4 +- .../src/share/vm/runtime/sharedRuntime.cpp | 42 +++++----- .../src/share/vm/runtime/sharedRuntime.hpp | 5 +- hotspot/src/share/vm/runtime/vframeArray.cpp | 2 +- 37 files changed, 420 insertions(+), 287 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index d5ea7dd43cd..6f496820090 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -377,6 +377,16 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { } + +void DeoptimizeStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + __ call(SharedRuntime::deopt_blob()->unpack_with_reexecution()); + __ delayed()->nop(); + ce->add_call_info_here(_info); + debug_only(__ should_not_reach_here()); +} + + void ArrayCopyStub::emit_code(LIR_Assembler* ce) { //---------------slow case: call to native----------------- __ bind(_entry); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 315e90019c6..4446addd9b5 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -378,12 +378,7 @@ int LIR_Assembler::emit_exception_handler() { int offset = code_offset(); - if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) { - __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - } - - __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); __ delayed()->nop(); debug_only(__ stop("should have gone to the caller");) assert(code_offset() - offset <= exception_handler_size, "overflow"); @@ -685,29 +680,29 @@ void LIR_Assembler::align_call(LIR_Code) { } -void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) { - __ call(entry, rtype); +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { + __ call(op->addr(), rtype); // the peephole pass fills the delay slot } -void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) { +void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { RelocationHolder rspec = virtual_call_Relocation::spec(pc()); __ set_oop((jobject)Universe::non_oop_word(), G5_inline_cache_reg); __ relocate(rspec); - __ call(entry, relocInfo::none); + __ call(op->addr(), relocInfo::none); // the peephole pass fills the delay slot } -void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { - add_debug_info_for_null_check_here(info); +void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { + add_debug_info_for_null_check_here(op->info()); __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); - if (__ is_simm13(vtable_offset) ) { - __ ld_ptr(G3_scratch, vtable_offset, G5_method); + if (__ is_simm13(op->vtable_offset())) { + __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method); } else { // This will generate 2 instructions - __ set(vtable_offset, G5_method); + __ set(op->vtable_offset(), G5_method); // ld_ptr, set_hi, set __ ld_ptr(G3_scratch, G5_method, G5_method); } @@ -717,6 +712,16 @@ void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { } +void LIR_Assembler::preserve_SP() { + Unimplemented(); +} + + +void LIR_Assembler::restore_SP() { + Unimplemented(); +} + + // load with 32-bit displacement int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) { int load_offset = code_offset(); diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 094fae4a973..17423a9b97b 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,17 +42,6 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { } -void C1_MacroAssembler::method_exit(bool restore_frame) { - // this code must be structured this way so that the return - // instruction can be a safepoint. - if (restore_frame) { - restore(); - } - retl(); - delayed()->nop(); -} - - void C1_MacroAssembler::explicit_null_check(Register base) { Unimplemented(); } diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 864d488ee2a..c88378f5796 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -677,7 +677,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ add(I7, frame::pc_return_offset, Oissuing_pc->after_save()); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - Oissuing_pc->after_save()); + G2_thread, Oissuing_pc->after_save()); __ verify_not_null_oop(Oexception->after_save()); __ jmp(O0, 0); __ delayed()->restore(); @@ -985,7 +985,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) { Label no_deopt; - Label no_handler; __ verify_not_null_oop(Oexception); @@ -1003,9 +1002,14 @@ void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_map // whether it had a handler or not we will deoptimize // by entering the deopt blob with a pending exception. +#ifdef ASSERT + Label done; __ tst(O0); - __ br(Assembler::zero, false, Assembler::pn, no_handler); + __ br(Assembler::notZero, false, Assembler::pn, done); __ delayed()->nop(); + __ stop("should have found address"); + __ bind(done); +#endif // restore the registers that were saved at the beginning and jump to the exception handler. restore_live_registers(sasm); @@ -1013,20 +1017,6 @@ void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_map __ jmp(O0, 0); __ delayed()->restore(); - __ bind(no_handler); - __ mov(L0, I7); // restore return address - - // restore exception oop - __ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), Oexception->after_save()); - __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_oop_offset())); - - __ restore(); - - AddressLiteral exc(Runtime1::entry_for(Runtime1::unwind_exception_id)); - __ jump_to(exc, G4); - __ delayed()->nop(); - - oop_maps->add_gc_map(call_offset, oop_map); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 604c2b9e4e4..9189f95d355 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -244,9 +244,10 @@ void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg) } -void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { +void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) { mov(arg_1, O0); - MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 1); + mov(arg_2, O1); + MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 2); } #endif /* CC_INTERP */ diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 61d6a528d7c..cbb6fb4e276 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,7 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exception = true); #ifndef CC_INTERP - void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1); + void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2); // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers tmp1, tmp2 and tmp3. diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 66c5a218dcc..091bc570d4c 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -379,7 +379,7 @@ class StubGenerator: public StubCodeGenerator { __ save_frame(0); // compensates for compiler weakness __ add(O7->after_save(), frame::pc_return_offset, Lscratch); // save the issuing PC BLOCK_COMMENT("call exception_handler_for_return_address"); - __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), Lscratch); + __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Lscratch); __ mov(O0, handler_reg); __ restore(); // compensates for compiler weakness diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index ada795d7ea1..8feef8bd8af 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1822,7 +1822,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ add(issuing_pc_addr, Oissuing_pc->after_save()); // likewise set I1 to a value local to the caller __ super_call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - Oissuing_pc->after_save()); + G2_thread, Oissuing_pc->after_save()); // The caller's SP was adjusted upon method entry to accomodate // the callee's non-argument locals. Undo that adjustment. diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index c513092c574..139c9564125 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -373,6 +373,14 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { } +void DeoptimizeStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + __ call(RuntimeAddress(SharedRuntime::deopt_blob()->unpack_with_reexecution())); + ce->add_call_info_here(_info); + debug_only(__ should_not_reach_here()); +} + + void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); __ bind(_entry); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 85f370a4c61..5907e058ce1 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -436,40 +436,18 @@ int LIR_Assembler::emit_exception_handler() { int offset = code_offset(); - // if the method does not have an exception handler, then there is - // no reason to search for one - if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) { - // the exception oop and pc are in rax, and rdx - // no other registers need to be preserved, so invalidate them - __ invalidate_registers(false, true, true, false, true, true); - - // check that there is really an exception - __ verify_not_null_oop(rax); - - // search an exception handler (rax: exception oop, rdx: throwing pc) - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); - - // if the call returns here, then the exception handler for particular - // exception doesn't exist -> unwind activation and forward exception to caller - } - - // the exception oop is in rax, + // the exception oop and pc are in rax, and rdx // no other registers need to be preserved, so invalidate them - __ invalidate_registers(false, true, true, true, true, true); + __ invalidate_registers(false, true, true, false, true, true); // check that there is really an exception __ verify_not_null_oop(rax); - // unlock the receiver/klass if necessary - // rax,: exception - ciMethod* method = compilation()->method(); - if (method->is_synchronized() && GenerateSynchronizationCode) { - monitorexit(FrameMap::rbx_oop_opr, FrameMap::rcx_opr, SYNC_header, 0, rax); - } + // search an exception handler (rax: exception oop, rdx: throwing pc) + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); + + __ stop("should not reach here"); - // unwind activation and forward exception to caller - // rax,: exception - __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); assert(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub(); @@ -495,8 +473,10 @@ int LIR_Assembler::emit_deopt_handler() { int offset = code_offset(); InternalAddress here(__ pc()); + __ pushptr(here.addr()); __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); + assert(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); @@ -593,7 +573,7 @@ void LIR_Assembler::return_op(LIR_Opr result) { } // Pop the stack before the safepoint code - __ leave(); + __ remove_frame(initial_frame_size_in_bytes()); bool result_is_oop = result->is_valid() ? result->is_oop() : false; @@ -2738,6 +2718,7 @@ void LIR_Assembler::align_call(LIR_Code code) { switch (code) { case lir_static_call: case lir_optvirtual_call: + case lir_dynamic_call: offset += NativeCall::displacement_offset; break; case lir_icvirtual_call: @@ -2753,30 +2734,41 @@ void LIR_Assembler::align_call(LIR_Code code) { } -void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) { +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(AddressLiteral(entry, rtype)); - add_call_info(code_offset(), info); + __ call(AddressLiteral(op->addr(), rtype)); + add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); } -void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) { +void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { RelocationHolder rh = virtual_call_Relocation::spec(pc()); __ movoop(IC_Klass, (jobject)Universe::non_oop_word()); assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(AddressLiteral(entry, rh)); - add_call_info(code_offset(), info); + __ call(AddressLiteral(op->addr(), rh)); + add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); } /* Currently, vtable-dispatch is only enabled for sparc platforms */ -void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { +void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { ShouldNotReachHere(); } + +void LIR_Assembler::preserve_SP() { + __ movptr(rbp, rsp); +} + + +void LIR_Assembler::restore_SP() { + __ movptr(rsp, rbp); +} + + void LIR_Assembler::emit_static_call_stub() { address call_pc = __ pc(); address stub = __ start_a_stub(call_stub_size); @@ -2829,10 +2821,12 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit } else { unwind_id = Runtime1::handle_exception_nofpu_id; } + __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); } else { - unwind_id = Runtime1::unwind_exception_id; + // remove the activation + __ remove_frame(initial_frame_size_in_bytes()); + __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); } - __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); // enough room for two byte trap __ nop(); diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index c340c87c0b1..0dc5b173a2f 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -317,14 +317,6 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { } -void C1_MacroAssembler::method_exit(bool restore_frame) { - if (restore_frame) { - leave(); - } - ret(0); -} - - void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { // Make sure there is enough stack space for this method's activation. // Note that we do this before doing an enter(). This matches the @@ -333,7 +325,7 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { // between the two compilers. generate_stack_overflow_check(frame_size_in_bytes); - enter(); + push(rbp); #ifdef TIERED // c2 leaves fpu stack dirty. Clean it on entry if (UseSSE < 2 ) { @@ -344,6 +336,12 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { } +void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) { + increment(rsp, frame_size_in_bytes); // Does not emit code for frame_size == 0 + pop(rbp); +} + + void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) { if (C1Breakpoint) int3(); inline_cache_check(receiver, ic_klass); diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index 3a447754ede..e3bf6fdae54 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -688,18 +688,21 @@ void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_map int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); oop_maps->add_gc_map(call_offset, oop_map); - // rax,: handler address or NULL if no handler exists + // rax,: handler address // will be the deopt blob if nmethod was deoptimized while we looked up // handler regardless of whether handler existed in the nmethod. // only rax, is valid at this time, all other registers have been destroyed by the runtime call __ invalidate_registers(false, true, true, true, true, true); +#ifdef ASSERT // Do we have an exception handler in the nmethod? - Label no_handler; Label done; __ testptr(rax, rax); - __ jcc(Assembler::zero, no_handler); + __ jcc(Assembler::notZero, done); + __ stop("no handler found"); + __ bind(done); +#endif // exception handler found // patch the return address -> the stub will directly return to the exception handler @@ -712,36 +715,14 @@ void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_map __ leave(); __ ret(0); - __ bind(no_handler); - // no exception handler found in this method, so the exception is - // forwarded to the caller (using the unwind code of the nmethod) - // there is no need to restore the registers - - // restore the real return address that was saved before the RT-call - __ movptr(real_return_addr, Address(rsp, temp_1_off * VMRegImpl::stack_slot_size)); - __ movptr(Address(rbp, 1*BytesPerWord), real_return_addr); - - // load address of JavaThread object for thread-local data - NOT_LP64(__ get_thread(thread);) - // restore exception oop into rax, (convention for unwind code) - __ movptr(exception_oop, Address(thread, JavaThread::exception_oop_offset())); - - // clear exception fields in JavaThread because they are no longer needed - // (fields must be cleared because they are processed by GC otherwise) - __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); - __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); - - // pop the stub frame off - __ leave(); - - generate_unwind_exception(sasm); - __ stop("should not reach here"); } void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // incoming parameters const Register exception_oop = rax; + // callee-saved copy of exception_oop during runtime call + const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14); // other registers used in this stub const Register exception_pc = rdx; const Register handler_addr = rbx; @@ -769,38 +750,39 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // clear the FPU stack in case any FPU results are left behind __ empty_FPU_stack(); - // leave activation of nmethod - __ leave(); - // store return address (is on top of stack after leave) + // save exception_oop in callee-saved register to preserve it during runtime calls + __ verify_not_null_oop(exception_oop); + __ movptr(exception_oop_callee_saved, exception_oop); + + NOT_LP64(__ get_thread(thread);) + // Get return address (is on top of stack after leave). __ movptr(exception_pc, Address(rsp, 0)); - __ verify_oop(exception_oop); - - // save exception oop from rax, to stack before call - __ push(exception_oop); - // search the exception handler address of the caller (using the return address) - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), exception_pc); - // rax,: exception handler address of the caller + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); + // rax: exception handler address of the caller - // only rax, is valid at this time, all other registers have been destroyed by the call - __ invalidate_registers(false, true, true, true, true, true); + // Only RAX and RSI are valid at this time, all other registers have been destroyed by the call. + __ invalidate_registers(false, true, true, true, false, true); // move result of call into correct register __ movptr(handler_addr, rax); - // restore exception oop in rax, (required convention of exception handler) - __ pop(exception_oop); + // Restore exception oop to RAX (required convention of exception handler). + __ movptr(exception_oop, exception_oop_callee_saved); - __ verify_oop(exception_oop); + // verify that there is really a valid exception in rax + __ verify_not_null_oop(exception_oop); // get throwing pc (= return address). // rdx has been destroyed by the call, so it must be set again // the pop is also necessary to simulate the effect of a ret(0) __ pop(exception_pc); - // verify that that there is really a valid exception in rax, - __ verify_not_null_oop(exception_oop); + // Restore SP from BP if the exception PC is a MethodHandle call site. + NOT_LP64(__ get_thread(thread);) + __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); // continue at exception handler (return address removed) // note: do *not* remove arguments when unwinding the @@ -808,9 +790,9 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // all arguments on the stack when entering the // runtime to determine the exception handler // (GC happens at call site with arguments!) - // rax,: exception oop + // rax: exception oop // rdx: throwing pc - // rbx,: exception handler + // rbx: exception handler __ jmp(handler_addr); } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 18f2fb7bcc7..e8276e5188f 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -369,7 +369,7 @@ class StubGenerator: public StubCodeGenerator { // The pending exception in Thread is converted into a Java-level exception. // // Contract with Java-level exception handlers: - // rax,: exception + // rax: exception // rdx: throwing pc // // NOTE: At entry of this stub, exception-pc must be on stack !! @@ -377,6 +377,12 @@ class StubGenerator: public StubCodeGenerator { address generate_forward_exception() { StubCodeMark mark(this, "StubRoutines", "forward exception"); address start = __ pc(); + const Register thread = rcx; + + // other registers used in this stub + const Register exception_oop = rax; + const Register handler_addr = rbx; + const Register exception_pc = rdx; // Upon entry, the sp points to the return address returning into Java // (interpreted or compiled) code; i.e., the return address becomes the @@ -389,8 +395,8 @@ class StubGenerator: public StubCodeGenerator { #ifdef ASSERT // make sure this code is only executed if there is a pending exception { Label L; - __ get_thread(rcx); - __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); + __ get_thread(thread); + __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); __ jcc(Assembler::notEqual, L); __ stop("StubRoutines::forward exception: no pending exception (1)"); __ bind(L); @@ -398,33 +404,40 @@ class StubGenerator: public StubCodeGenerator { #endif // compute exception handler into rbx, - __ movptr(rax, Address(rsp, 0)); + __ get_thread(thread); + __ movptr(exception_pc, Address(rsp, 0)); BLOCK_COMMENT("call exception_handler_for_return_address"); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rax); - __ mov(rbx, rax); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); + __ mov(handler_addr, rax); - // setup rax, & rdx, remove return address & clear pending exception - __ get_thread(rcx); - __ pop(rdx); - __ movptr(rax, Address(rcx, Thread::pending_exception_offset())); - __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD); + // setup rax & rdx, remove return address & clear pending exception + __ get_thread(thread); + __ pop(exception_pc); + __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); #ifdef ASSERT // make sure exception is set { Label L; - __ testptr(rax, rax); + __ testptr(exception_oop, exception_oop); __ jcc(Assembler::notEqual, L); __ stop("StubRoutines::forward exception: no pending exception (2)"); __ bind(L); } #endif + // Verify that there is really a valid exception in RAX. + __ verify_oop(exception_oop); + + // Restore SP from BP if the exception PC is a MethodHandle call site. + __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); + // continue at exception handler (return address removed) - // rax,: exception - // rbx,: exception handler + // rax: exception + // rbx: exception handler // rdx: throwing pc - __ verify_oop(rax); - __ jmp(rbx); + __ jmp(handler_addr); return start; } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 9415241f11d..516a7826a92 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -466,7 +466,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("call exception_handler_for_return_address"); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - c_rarg0); + r15_thread, c_rarg0); __ mov(rbx, rax); // setup rax & rdx, remove return address & clear pending exception diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index eecfb3fd114..6174b2d8bea 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -1550,6 +1550,7 @@ int AbstractInterpreter::layout_activation(methodOop method, void TemplateInterpreterGenerator::generate_throw_exception() { // Entry point in previous activation (i.e., if the caller was interpreted) Interpreter::_rethrow_exception_entry = __ pc(); + const Register thread = rcx; // Restore sp to interpreter_frame_last_sp even though we are going // to empty the expression stack for the exception processing. @@ -1598,10 +1599,10 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Set the popframe_processing bit in pending_popframe_condition indicating that we are // currently handling popframe, so that call_VMs that may happen later do not trigger new // popframe handling cycles. - __ get_thread(rcx); - __ movl(rdx, Address(rcx, JavaThread::popframe_condition_offset())); + __ get_thread(thread); + __ movl(rdx, Address(thread, JavaThread::popframe_condition_offset())); __ orl(rdx, JavaThread::popframe_processing_bit); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), rdx); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), rdx); { // Check to see whether we are returning to a deoptimized frame. @@ -1629,8 +1630,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ subptr(rdi, rax); __ addptr(rdi, wordSize); // Save these arguments - __ get_thread(rcx); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), rcx, rax, rdi); + __ get_thread(thread); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), thread, rax, rdi); __ remove_activation(vtos, rdx, /* throw_monitor_exception */ false, @@ -1638,8 +1639,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { /* notify_jvmdi */ false); // Inform deoptimization that it is responsible for restoring these arguments - __ get_thread(rcx); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit); + __ get_thread(thread); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit); // Continue in deoptimization handler __ jmp(rdx); @@ -1665,12 +1666,12 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // expression stack if necessary. __ mov(rax, rsp); __ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ get_thread(rcx); + __ get_thread(thread); // PC must point into interpreter here - __ set_last_Java_frame(rcx, noreg, rbp, __ pc()); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), rcx, rax, rbx); - __ get_thread(rcx); - __ reset_last_Java_frame(rcx, true, true); + __ set_last_Java_frame(thread, noreg, rbp, __ pc()); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), thread, rax, rbx); + __ get_thread(thread); + __ reset_last_Java_frame(thread, true, true); // Restore the last_sp and null it out __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); @@ -1684,8 +1685,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { } // Clear the popframe condition flag - __ get_thread(rcx); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); + __ get_thread(thread); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); __ dispatch_next(vtos); // end of PopFrame support @@ -1694,27 +1695,27 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(rax); - __ get_thread(rcx); - __ movptr(Address(rcx, JavaThread::vm_result_offset()), rax); + __ get_thread(thread); + __ movptr(Address(thread, JavaThread::vm_result_offset()), rax); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, rdx, false, true, false); // restore exception - __ get_thread(rcx); - __ movptr(rax, Address(rcx, JavaThread::vm_result_offset())); - __ movptr(Address(rcx, JavaThread::vm_result_offset()), NULL_WORD); + __ get_thread(thread); + __ movptr(rax, Address(thread, JavaThread::vm_result_offset())); + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); __ verify_oop(rax); // Inbetween activations - previous activation type unknown yet // compute continuation point - the continuation point expects // the following registers set up: // - // rax,: exception + // rax: exception // rdx: return address/pc that threw exception // rsp: expression stack of caller - // rbp,: rbp, of caller + // rbp: rbp, of caller __ push(rax); // save exception __ push(rdx); // save return address - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rdx); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, rdx); __ mov(rbx, rax); // save exception handler __ pop(rdx); // restore return address __ pop(rax); // restore exception @@ -1728,6 +1729,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) { address entry = __ pc(); + const Register thread = rcx; __ restore_bcp(); __ restore_locals(); @@ -1735,8 +1737,8 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state __ empty_FPU_stack(); __ load_earlyret_value(state); - __ get_thread(rcx); - __ movptr(rcx, Address(rcx, JavaThread::jvmti_thread_state_offset())); + __ get_thread(thread); + __ movptr(rcx, Address(thread, JavaThread::jvmti_thread_state_offset())); const Address cond_addr(rcx, JvmtiThreadState::earlyret_state_offset()); // Clear the earlyret state diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 44225441635..da5a0eca94d 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1741,7 +1741,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ push(rdx); // save return address __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - rdx); + r15_thread, rdx); __ mov(rbx, rax); // save exception handler __ pop(rdx); // restore return address __ pop(rax); // restore exception diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index 8efd3b58009..d2e59e3c561 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -222,11 +222,15 @@ void Canonicalizer::do_ArrayLength (ArrayLength* x) { } } else { LoadField* lf = x->array()->as_LoadField(); - if (lf != NULL && lf->field()->is_constant()) { - ciObject* c = lf->field()->constant_value().as_object(); - if (c->is_array()) { - ciArray* array = (ciArray*) c; - set_constant(array->length()); + if (lf != NULL) { + ciField* field = lf->field(); + if (field->is_constant() && field->is_static()) { + // final static field + ciObject* c = field->constant_value().as_object(); + if (c->is_array()) { + ciArray* array = (ciArray*) c; + set_constant(array->length()); + } } } } diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp index 4c47e777b2b..d5e2cea755c 100644 --- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -415,6 +415,28 @@ class PatchingStub: public CodeStub { }; +//------------------------------------------------------------------------------ +// DeoptimizeStub +// +class DeoptimizeStub : public CodeStub { +private: + CodeEmitInfo* _info; + +public: + DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {} + + virtual void emit_code(LIR_Assembler* e); + virtual CodeEmitInfo* info() const { return _info; } + virtual bool is_exception_throw_stub() const { return true; } + virtual void visit(LIR_OpVisitState* visitor) { + visitor->do_slow_case(_info); + } +#ifndef PRODUCT + virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); } +#endif // PRODUCT +}; + + class SimpleExceptionStub: public CodeStub { private: LIR_Opr _obj; diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index f567d6e120d..8fc646cca55 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1524,18 +1524,14 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code = Bytecodes::_invokespecial; } - if (code == Bytecodes::_invokedynamic) { - BAILOUT("invokedynamic NYI"); // FIXME - return; - } - // NEEDS_CLEANUP // I've added the target-is_loaded() test below but I don't really understand // how klass->is_loaded() can be true and yet target->is_loaded() is false. // this happened while running the JCK invokevirtual tests under doit. TKR ciMethod* cha_monomorphic_target = NULL; ciMethod* exact_target = NULL; - if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded()) { + if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && + !target->is_method_handle_invoke()) { Value receiver = NULL; ciInstanceKlass* receiver_klass = NULL; bool type_is_exact = false; @@ -1681,11 +1677,20 @@ void GraphBuilder::invoke(Bytecodes::Code code) { CHECK_BAILOUT(); // inlining not successful => standard invoke - bool is_static = code == Bytecodes::_invokestatic; - ValueType* result_type = as_ValueType(target->return_type()); - Values* args = state()->pop_arguments(target->arg_size_no_receiver()); - Value recv = is_static ? NULL : apop(); bool is_loaded = target->is_loaded(); + bool has_receiver = + code == Bytecodes::_invokespecial || + code == Bytecodes::_invokevirtual || + code == Bytecodes::_invokeinterface; + bool is_invokedynamic = code == Bytecodes::_invokedynamic; + ValueType* result_type = as_ValueType(target->return_type()); + + // We require the debug info to be the "state before" because + // invokedynamics may deoptimize. + ValueStack* state_before = is_invokedynamic ? state()->copy() : NULL; + + Values* args = state()->pop_arguments(target->arg_size_no_receiver()); + Value recv = has_receiver ? apop() : NULL; int vtable_index = methodOopDesc::invalid_vtable_index; #ifdef SPARC @@ -1723,7 +1728,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { profile_call(recv, target_klass); } - Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target); + Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before); // push result append_split(result); @@ -2862,20 +2867,18 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) _initial_state = state_at_entry(); start_block->merge(_initial_state); - BlockBegin* sync_handler = NULL; - if (method()->is_synchronized() || _compilation->env()->dtrace_method_probes()) { - // setup an exception handler to do the unlocking and/or notification - sync_handler = new BlockBegin(-1); - sync_handler->set(BlockBegin::exception_entry_flag); - sync_handler->set(BlockBegin::is_on_work_list_flag); - sync_handler->set(BlockBegin::default_exception_handler_flag); + // setup an exception handler to do the unlocking and/or + // notification and unwind the frame. + BlockBegin* sync_handler = new BlockBegin(-1); + sync_handler->set(BlockBegin::exception_entry_flag); + sync_handler->set(BlockBegin::is_on_work_list_flag); + sync_handler->set(BlockBegin::default_exception_handler_flag); - ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); - XHandler* h = new XHandler(desc); - h->set_entry_block(sync_handler); - scope_data()->xhandlers()->append(h); - scope_data()->set_has_handler(); - } + ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); + XHandler* h = new XHandler(desc); + h->set_entry_block(sync_handler); + scope_data()->xhandlers()->append(h); + scope_data()->set_has_handler(); // complete graph _vmap = new ValueMap(); diff --git a/hotspot/src/share/vm/c1/c1_IR.cpp b/hotspot/src/share/vm/c1/c1_IR.cpp index 7ecf4812b08..176697b6644 100644 --- a/hotspot/src/share/vm/c1/c1_IR.cpp +++ b/hotspot/src/share/vm/c1/c1_IR.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,10 +259,10 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, bool lock_stack_only) } -void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { +void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke) { // record the safepoint before recording the debug info for enclosing scopes recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); - _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/); + _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, is_method_handle_invoke); recorder->end_safepoint(pc_offset); } diff --git a/hotspot/src/share/vm/c1/c1_IR.hpp b/hotspot/src/share/vm/c1/c1_IR.hpp index 32ed4a40d00..0af76f3497e 100644 --- a/hotspot/src/share/vm/c1/c1_IR.hpp +++ b/hotspot/src/share/vm/c1/c1_IR.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,7 +242,7 @@ class IRScopeDebugInfo: public CompilationResourceObj { //Whether we should reexecute this bytecode for deopt bool should_reexecute(); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost) { + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) { if (caller() != NULL) { // Order is significant: Must record caller first. caller()->record_debug_info(recorder, pc_offset, false/*topmost*/); @@ -252,7 +252,6 @@ class IRScopeDebugInfo: public CompilationResourceObj { DebugToken* monvals = recorder->create_monitor_values(monitors()); // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; - bool is_method_handle_invoke = false; bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } @@ -303,7 +302,7 @@ class CodeEmitInfo: public CompilationResourceObj { int bci() const { return _bci; } void add_register_oop(LIR_Opr opr); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset); + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke = false); CodeEmitInfo* next() const { return _next; } void set_next(CodeEmitInfo* next) { _next = next; } diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 4ac089fa337..265bc7c1849 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -334,13 +334,14 @@ void Intrinsic::state_values_do(void f(Value*)) { Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args, - int vtable_index, ciMethod* target) + int vtable_index, ciMethod* target, ValueStack* state_before) : StateSplit(result_type) , _code(code) , _recv(recv) , _args(args) , _vtable_index(vtable_index) , _target(target) + , _state_before(state_before) { set_flag(TargetIsLoadedFlag, target->is_loaded()); set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method()); @@ -355,6 +356,9 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0)); if (has_receiver()) { _signature->append(as_BasicType(receiver()->type())); + } else if (is_invokedynamic()) { + // Add the synthetic MethodHandle argument to the signature. + _signature->append(T_OBJECT); } for (int i = 0; i < number_of_arguments(); i++) { ValueType* t = argument_at(i)->type(); @@ -364,6 +368,13 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* } +void Invoke::state_values_do(void f(Value*)) { + StateSplit::state_values_do(f); + if (state_before() != NULL) state_before()->values_do(f); + if (state() != NULL) state()->values_do(f); +} + + // Implementation of Contant intx Constant::hash() const { if (_state == NULL) { diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 86087b65f44..92e020a873a 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1134,17 +1134,18 @@ BASE(StateSplit, Instruction) LEAF(Invoke, StateSplit) private: - Bytecodes::Code _code; - Value _recv; - Values* _args; - BasicTypeList* _signature; - int _vtable_index; - ciMethod* _target; + Bytecodes::Code _code; + Value _recv; + Values* _args; + BasicTypeList* _signature; + int _vtable_index; + ciMethod* _target; + ValueStack* _state_before; // Required for deoptimization. public: // creation Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args, - int vtable_index, ciMethod* target); + int vtable_index, ciMethod* target, ValueStack* state_before); // accessors Bytecodes::Code code() const { return _code; } @@ -1155,6 +1156,7 @@ LEAF(Invoke, StateSplit) int vtable_index() const { return _vtable_index; } BasicTypeList* signature() const { return _signature; } ciMethod* target() const { return _target; } + ValueStack* state_before() const { return _state_before; } // Returns false if target is not loaded bool target_is_final() const { return check_flag(TargetIsFinalFlag); } @@ -1162,6 +1164,9 @@ LEAF(Invoke, StateSplit) // Returns false if target is not loaded bool target_is_strictfp() const { return check_flag(TargetIsStrictfpFlag); } + // JSR 292 support + bool is_invokedynamic() const { return code() == Bytecodes::_invokedynamic; } + // generic virtual bool can_trap() const { return true; } virtual void input_values_do(void f(Value*)) { @@ -1169,6 +1174,7 @@ LEAF(Invoke, StateSplit) if (has_receiver()) f(&_recv); for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i)); } + virtual void state_values_do(void f(Value*)); }; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index b967785fbbb..fb8cf3d0109 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -689,9 +689,10 @@ void LIR_OpVisitState::visit(LIR_Op* op) { case lir_static_call: case lir_optvirtual_call: case lir_icvirtual_call: - case lir_virtual_call: { - assert(op->as_OpJavaCall() != NULL, "must be"); - LIR_OpJavaCall* opJavaCall = (LIR_OpJavaCall*)op; + case lir_virtual_call: + case lir_dynamic_call: { + LIR_OpJavaCall* opJavaCall = op->as_OpJavaCall(); + assert(opJavaCall != NULL, "must be"); if (opJavaCall->_receiver->is_valid()) do_input(opJavaCall->_receiver); @@ -1590,6 +1591,7 @@ const char * LIR_Op::name() const { case lir_optvirtual_call: s = "optvirtual"; break; case lir_icvirtual_call: s = "icvirtual"; break; case lir_virtual_call: s = "virtual"; break; + case lir_dynamic_call: s = "dynamic"; break; // LIR_OpArrayCopy case lir_arraycopy: s = "arraycopy"; break; // LIR_OpLock diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index fb51de4ca2d..6ee83f69445 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -840,6 +840,7 @@ enum LIR_Code { , lir_optvirtual_call , lir_icvirtual_call , lir_virtual_call + , lir_dynamic_call , end_opJavaCall , begin_opArrayCopy , lir_arraycopy @@ -1052,6 +1053,16 @@ class LIR_OpJavaCall: public LIR_OpCall { LIR_Opr receiver() const { return _receiver; } ciMethod* method() const { return _method; } + // JSR 292 support. + bool is_invokedynamic() const { return code() == lir_dynamic_call; } + bool is_method_handle_invoke() const { + return + is_invokedynamic() // An invokedynamic is always a MethodHandle call site. + || + (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() && + method()->name() == ciSymbol::invoke_name()); + } + intptr_t vtable_offset() const { assert(_code == lir_virtual_call, "only have vtable for real vcall"); return (intptr_t) addr(); @@ -1766,6 +1777,10 @@ class LIR_List: public CompilationResourceObj { intptr_t vtable_offset, LIR_OprList* arguments, CodeEmitInfo* info) { append(new LIR_OpJavaCall(lir_virtual_call, method, receiver, result, vtable_offset, arguments, info)); } + void call_dynamic(ciMethod* method, LIR_Opr receiver, LIR_Opr result, + address dest, LIR_OprList* arguments, CodeEmitInfo* info) { + append(new LIR_OpJavaCall(lir_dynamic_call, method, receiver, result, dest, arguments, info)); + } void get_thread(LIR_Opr result) { append(new LIR_Op0(lir_get_thread, result)); } void word_align() { append(new LIR_Op0(lir_word_align)); } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index 8e31b94ec01..a58051f1a33 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -301,9 +301,9 @@ void LIR_Assembler::add_debug_info_for_branch(CodeEmitInfo* info) { } -void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo) { +void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke) { flush_debug_info(pc_offset); - cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset); + cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset, is_method_handle_invoke); if (cinfo->exception_handlers() != NULL) { compilation()->add_exception_handlers_for_pco(pc_offset, cinfo->exception_handlers()); } @@ -413,6 +413,12 @@ void LIR_Assembler::emit_rtcall(LIR_OpRTCall* op) { void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { verify_oop_map(op->info()); + // JSR 292 + // Preserve the SP over MethodHandle call sites. + if (op->is_method_handle_invoke()) { + preserve_SP(); + } + if (os::is_MP()) { // must align calls sites, otherwise they can't be updated atomically on MP hardware align_call(op->code()); @@ -423,19 +429,25 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { switch (op->code()) { case lir_static_call: - call(op->addr(), relocInfo::static_call_type, op->info()); + call(op, relocInfo::static_call_type); break; case lir_optvirtual_call: - call(op->addr(), relocInfo::opt_virtual_call_type, op->info()); + case lir_dynamic_call: + call(op, relocInfo::opt_virtual_call_type); break; case lir_icvirtual_call: - ic_call(op->addr(), op->info()); + ic_call(op); break; case lir_virtual_call: - vtable_call(op->vtable_offset(), op->info()); + vtable_call(op); break; default: ShouldNotReachHere(); } + + if (op->is_method_handle_invoke()) { + restore_SP(); + } + #if defined(X86) && defined(TIERED) // C2 leave fpu stack dirty clean it if (UseSSE < 2) { diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 8219b534eb0..01de986d8a9 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -82,7 +82,7 @@ class LIR_Assembler: public CompilationResourceObj { Address as_Address_hi(LIR_Address* addr); // debug information - void add_call_info(int pc_offset, CodeEmitInfo* cinfo); + void add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke = false); void add_debug_info_for_branch(CodeEmitInfo* info); void add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo); void add_debug_info_for_div0_here(CodeEmitInfo* info); @@ -205,9 +205,12 @@ class LIR_Assembler: public CompilationResourceObj { void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result); - void ic_call(address destination, CodeEmitInfo* info); - void vtable_call(int vtable_offset, CodeEmitInfo* info); - void call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info); + void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); + void ic_call( LIR_OpJavaCall* op); + void vtable_call( LIR_OpJavaCall* op); + + void preserve_SP(); + void restore_SP(); void osr_entry(); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 05e479f26bf..1dec4e177b7 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2284,7 +2284,7 @@ void LIRGenerator::do_OsrEntry(OsrEntry* x) { void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) { - int i = x->has_receiver() ? 1 : 0; + int i = (x->has_receiver() || x->is_invokedynamic()) ? 1 : 0; for (; i < args->length(); i++) { LIRItem* param = args->at(i); LIR_Opr loc = arg_list->at(i); @@ -2322,6 +2322,10 @@ LIRItemList* LIRGenerator::invoke_visit_arguments(Invoke* x) { LIRItem* receiver = new LIRItem(x->receiver(), this); argument_items->append(receiver); } + if (x->is_invokedynamic()) { + // Insert a dummy for the synthetic MethodHandle argument. + argument_items->append(NULL); + } int idx = x->has_receiver() ? 1 : 0; for (int i = 0; i < x->number_of_arguments(); i++) { LIRItem* param = new LIRItem(x->argument_at(i), this); @@ -2371,6 +2375,10 @@ void LIRGenerator::do_Invoke(Invoke* x) { CodeEmitInfo* info = state_for(x, x->state()); + // invokedynamics can deoptimize. + bool is_invokedynamic = x->code() == Bytecodes::_invokedynamic; + CodeEmitInfo* deopt_info = is_invokedynamic ? state_for(x, x->state_before()) : NULL; + invoke_load_arguments(x, args, arg_list); if (x->has_receiver()) { @@ -2407,6 +2415,47 @@ void LIRGenerator::do_Invoke(Invoke* x) { __ call_virtual(x->target(), receiver, result_register, vtable_offset, arg_list, info); } break; + case Bytecodes::_invokedynamic: { + ciBytecodeStream bcs(x->scope()->method()); + bcs.force_bci(x->bci()); + assert(bcs.cur_bc() == Bytecodes::_invokedynamic, "wrong stream"); + ciCPCache* cpcache = bcs.get_cpcache(); + + // Get CallSite offset from constant pool cache pointer. + int index = bcs.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // If this invokedynamic call site hasn't been executed yet in + // the interpreter, the CallSite object in the constant pool + // cache is still null and we need to deoptimize. + if (cpcache->is_f1_null_at(index)) { + // Cannot re-use same xhandlers for multiple CodeEmitInfos, so + // clone all handlers. This is handled transparently in other + // places by the CodeEmitInfo cloning logic but is handled + // specially here because a stub isn't being used. + x->set_exception_handlers(new XHandlers(x->exception_handlers())); + + DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info); + __ jump(deopt_stub); + } + + // Use the receiver register for the synthetic MethodHandle + // argument. + receiver = LIR_Assembler::receiverOpr(); + LIR_Opr tmp = new_register(objectType); + + // Load CallSite object from constant pool cache. + __ oop2reg(cpcache->constant_encoding(), tmp); + __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); + + // Load target MethodHandle from CallSite object. + __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); + + __ call_dynamic(x->target(), receiver, result_register, + SharedRuntime::get_resolve_opt_virtual_call_stub(), + arg_list, info); + break; + } default: ShouldNotReachHere(); break; diff --git a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp index 79f3969f7a1..6d2ffd03510 100644 --- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ class C1_MacroAssembler: public MacroAssembler { void inline_cache_check(Register receiver, Register iCache); void build_frame(int frame_size_in_bytes); - void method_exit(bool restore_frame); + void remove_frame(int frame_size_in_bytes); void unverified_entry(Register receiver, Register ic_klass); void verified_entry(); diff --git a/hotspot/src/share/vm/ci/ciCPCache.cpp b/hotspot/src/share/vm/ci/ciCPCache.cpp index 87bd409a615..1c8e3c810c3 100644 --- a/hotspot/src/share/vm/ci/ciCPCache.cpp +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,16 @@ size_t ciCPCache::get_f1_offset(int index) { } +// ------------------------------------------------------------------ +// ciCPCache::is_f1_null_at +bool ciCPCache::is_f1_null_at(int index) { + VM_ENTRY_MARK; + constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop(); + oop f1 = cpcache->secondary_entry_at(index)->f1(); + return (f1 == NULL); +} + + // ------------------------------------------------------------------ // ciCPCache::print // diff --git a/hotspot/src/share/vm/ci/ciCPCache.hpp b/hotspot/src/share/vm/ci/ciCPCache.hpp index 48e0c3b8fe7..11ca98d2a55 100644 --- a/hotspot/src/share/vm/ci/ciCPCache.hpp +++ b/hotspot/src/share/vm/ci/ciCPCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,5 +39,7 @@ public: // requested entry. size_t get_f1_offset(int index); + bool is_f1_null_at(int index); + void print(); }; diff --git a/hotspot/src/share/vm/includeDB_compiler1 b/hotspot/src/share/vm/includeDB_compiler1 index 72cedfe5a89..a263ec199d7 100644 --- a/hotspot/src/share/vm/includeDB_compiler1 +++ b/hotspot/src/share/vm/includeDB_compiler1 @@ -1,5 +1,5 @@ // -// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. +// Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -246,6 +246,7 @@ c1_LIRGenerator.cpp c1_LIRAssembler.hpp c1_LIRGenerator.cpp c1_LIRGenerator.hpp c1_LIRGenerator.cpp c1_ValueStack.hpp c1_LIRGenerator.cpp ciArrayKlass.hpp +c1_LIRGenerator.cpp ciCPCache.hpp c1_LIRGenerator.cpp ciInstance.hpp c1_LIRGenerator.cpp heapRegion.hpp c1_LIRGenerator.cpp sharedRuntime.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 74b5f71a50f..557db70983b 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -541,6 +541,7 @@ ciConstantPoolCache.hpp resourceArea.hpp ciCPCache.cpp cpCacheOop.hpp ciCPCache.cpp ciCPCache.hpp +ciCPCache.cpp ciUtilities.hpp ciCPCache.hpp ciClassList.hpp ciCPCache.hpp ciObject.hpp diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index c2d5ca7df88..d293f05114a 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -864,7 +864,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t thread->set_exception_handler_pc(handler_address); thread->set_exception_stack_size(0); - // Check if the exception PC is a MethodHandle call. + // Check if the exception PC is a MethodHandle call site. thread->set_is_method_handle_exception(nm->is_method_handle_return(pc)); } @@ -952,7 +952,7 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r thread->set_vm_result(exception); // Frame not compiled (handles deoptimization blob) - return SharedRuntime::raw_exception_handler_for_return_address(ret_pc); + return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); } diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index bc79954b978..0e465e46cbe 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -256,7 +256,7 @@ JRT_END // The continuation address is the entry point of the exception handler of the // previous frame depending on the return address. -address SharedRuntime::raw_exception_handler_for_return_address(address return_address) { +address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) { assert(frame::verify_return_pc(return_address), "must be a return pc"); // the fastest case first @@ -264,6 +264,8 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a if (blob != NULL && blob->is_nmethod()) { nmethod* code = (nmethod*)blob; assert(code != NULL, "nmethod must be present"); + // Check if the return address is a MethodHandle call site. + thread->set_is_method_handle_exception(code->is_method_handle_return(return_address)); // native nmethods don't have exception handlers assert(!code->is_native_method(), "no exception handler"); assert(code->header_begin() != code->exception_begin(), "no exception handler"); @@ -289,6 +291,8 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a if (blob->is_nmethod()) { nmethod* code = (nmethod*)blob; assert(code != NULL, "nmethod must be present"); + // Check if the return address is a MethodHandle call site. + thread->set_is_method_handle_exception(code->is_method_handle_return(return_address)); assert(code->header_begin() != code->exception_begin(), "no exception handler"); return code->exception_begin(); } @@ -309,10 +313,11 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a } -JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(address return_address)) - return raw_exception_handler_for_return_address(return_address); +JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(JavaThread* thread, address return_address)) + return raw_exception_handler_for_return_address(thread, return_address); JRT_END + address SharedRuntime::get_poll_stub(address pc) { address stub; // Look up the code blob @@ -465,16 +470,6 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, t = table.entry_for(catch_pco, -1, 0); } -#ifdef COMPILER1 - if (nm->is_compiled_by_c1() && t == NULL && handler_bci == -1) { - // Exception is not handled by this frame so unwind. Note that - // this is not the same as how C2 does this. C2 emits a table - // entry that dispatches to the unwind code in the nmethod. - return NULL; - } -#endif /* COMPILER1 */ - - if (t == NULL) { tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d", ret_pc, handler_bci); tty->print_cr(" Exception:"); @@ -892,12 +887,13 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, RegisterMap cbl_map(thread, false); frame caller_frame = thread->last_frame().sender(&cbl_map); - CodeBlob* cb = caller_frame.cb(); - guarantee(cb != NULL && cb->is_nmethod(), "must be called from nmethod"); + CodeBlob* caller_cb = caller_frame.cb(); + guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod"); + nmethod* caller_nm = caller_cb->as_nmethod_or_null(); // make sure caller is not getting deoptimized // and removed before we are done with it. // CLEANUP - with lazy deopt shouldn't need this lock - nmethodLocker caller_lock((nmethod*)cb); + nmethodLocker caller_lock(caller_nm); // determine call info & receiver @@ -929,6 +925,13 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, } #endif + // JSR 292 + // If the resolved method is a MethodHandle invoke target the call + // site must be a MethodHandle call site. + if (callee_method->is_method_handle_invoke()) { + assert(caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site"); + } + // Compute entry points. This might require generation of C2I converter // frames, so we cannot be holding any locks here. Furthermore, the // computation of the entry points is independent of patching the call. We @@ -940,13 +943,12 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, StaticCallInfo static_call_info; CompiledICInfo virtual_call_info; - // Make sure the callee nmethod does not get deoptimized and removed before // we are done patching the code. - nmethod* nm = callee_method->code(); - nmethodLocker nl_callee(nm); + nmethod* callee_nm = callee_method->code(); + nmethodLocker nl_callee(callee_nm); #ifdef ASSERT - address dest_entry_point = nm == NULL ? 0 : nm->entry_point(); // used below + address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below #endif if (is_virtual) { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 26aee620846..a540065c20d 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -96,10 +96,9 @@ class SharedRuntime: AllStatic { static jdouble dexp(jdouble x); static jdouble dpow(jdouble x, jdouble y); - // exception handling across interpreter/compiler boundaries - static address raw_exception_handler_for_return_address(address return_address); - static address exception_handler_for_return_address(address return_address); + static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address); + static address exception_handler_for_return_address(JavaThread* thread, address return_address); #ifndef SERIALGC // G1 write barriers diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 6a9aac2efc9..2fb27dfd920 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -223,7 +223,7 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, break; case Deoptimization::Unpack_exception: // exception is pending - pc = SharedRuntime::raw_exception_handler_for_return_address(pc); + pc = SharedRuntime::raw_exception_handler_for_return_address(thread, pc); // [phh] We're going to end up in some handler or other, so it doesn't // matter what mdp we point to. See exception_handler_for_exception() // in interpreterRuntime.cpp. From 7dcf59914ea0c7d83bd0dfabf0b5d2db85855e29 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 5 Mar 2010 13:58:34 +0100 Subject: [PATCH 20/33] 6932496: c1: deoptimization of jsr subroutine fails on sparcv9 Store jsr ret bci as intptr constant in c1 debug info Reviewed-by: never --- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 7 ++- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 5 +- hotspot/src/share/vm/c1/c1_LIR.cpp | 5 +- hotspot/src/share/vm/c1/c1_LIR.hpp | 8 +-- hotspot/src/share/vm/c1/c1_LinearScan.cpp | 9 ++++ .../test/compiler/6932496/Test6932496.java | 51 +++++++++++++++++++ 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 hotspot/test/compiler/6932496/Test6932496.java diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 4446addd9b5..05804c52d7a 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -1072,7 +1072,8 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { case T_INT: - case T_FLOAT: { + case T_FLOAT: + case T_ADDRESS: { Register src_reg = O7; int value = c->as_jint_bits(); if (value == 0) { @@ -1128,7 +1129,8 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi } switch (c->type()) { case T_INT: - case T_FLOAT: { + case T_FLOAT: + case T_ADDRESS: { LIR_Opr tmp = FrameMap::O7_opr; int value = c->as_jint_bits(); if (value == 0) { @@ -1200,6 +1202,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod switch (c->type()) { case T_INT: + case T_ADDRESS: { jint con = c->as_jint(); if (to_reg->is_single_cpu()) { diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 5907e058ce1..eb1ee51bd82 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -628,7 +628,8 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { - case T_INT: { + case T_INT: + case T_ADDRESS: { assert(patch_code == lir_patch_none, "no patching handled here"); __ movl(dest->as_register(), c->as_jint()); break; @@ -711,6 +712,7 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { switch (c->type()) { case T_INT: // fall through case T_FLOAT: + case T_ADDRESS: __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); break; @@ -746,6 +748,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi switch (type) { case T_INT: // fall through case T_FLOAT: + case T_ADDRESS: __ movl(as_Address(addr), c->as_jint_bits()); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index fb8cf3d0109..ce8efb9b413 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -76,7 +76,7 @@ LIR_Opr LIR_OprFact::value_type(ValueType* type) { return LIR_OprFact::oopConst(type->as_ObjectType()->encoding()); } } - case addressTag: return LIR_OprFact::intConst(type->as_AddressConstant()->value()); + case addressTag: return LIR_OprFact::addressConst(type->as_AddressConstant()->value()); case intTag : return LIR_OprFact::intConst(type->as_IntConstant()->value()); case floatTag : return LIR_OprFact::floatConst(type->as_FloatConstant()->value()); case longTag : return LIR_OprFact::longConst(type->as_LongConstant()->value()); @@ -89,7 +89,7 @@ LIR_Opr LIR_OprFact::value_type(ValueType* type) { LIR_Opr LIR_OprFact::dummy_value_type(ValueType* type) { switch (type->tag()) { case objectTag: return LIR_OprFact::oopConst(NULL); - case addressTag: + case addressTag:return LIR_OprFact::addressConst(0); case intTag: return LIR_OprFact::intConst(0); case floatTag: return LIR_OprFact::floatConst(0.0); case longTag: return LIR_OprFact::longConst(0); @@ -1411,6 +1411,7 @@ void LIR_OprDesc::print(outputStream* out) const { // LIR_Address void LIR_Const::print_value_on(outputStream* out) const { switch (type()) { + case T_ADDRESS:out->print("address:%d",as_jint()); break; case T_INT: out->print("int:%d", as_jint()); break; case T_LONG: out->print("lng:%lld", as_jlong()); break; case T_FLOAT: out->print("flt:%f", as_jfloat()); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 6ee83f69445..4ce123a176e 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -85,9 +85,10 @@ class LIR_Const: public LIR_OprPtr { void type_check(BasicType t) const { assert(type() == t, "type check"); } void type_check(BasicType t1, BasicType t2) const { assert(type() == t1 || type() == t2, "type check"); } + void type_check(BasicType t1, BasicType t2, BasicType t3) const { assert(type() == t1 || type() == t2 || type() == t3, "type check"); } public: - LIR_Const(jint i) { _value.set_type(T_INT); _value.set_jint(i); } + LIR_Const(jint i, bool is_address=false) { _value.set_type(is_address?T_ADDRESS:T_INT); _value.set_jint(i); } LIR_Const(jlong l) { _value.set_type(T_LONG); _value.set_jlong(l); } LIR_Const(jfloat f) { _value.set_type(T_FLOAT); _value.set_jfloat(f); } LIR_Const(jdouble d) { _value.set_type(T_DOUBLE); _value.set_jdouble(d); } @@ -105,7 +106,7 @@ class LIR_Const: public LIR_OprPtr { virtual BasicType type() const { return _value.get_type(); } virtual LIR_Const* as_constant() { return this; } - jint as_jint() const { type_check(T_INT ); return _value.get_jint(); } + jint as_jint() const { type_check(T_INT, T_ADDRESS); return _value.get_jint(); } jlong as_jlong() const { type_check(T_LONG ); return _value.get_jlong(); } jfloat as_jfloat() const { type_check(T_FLOAT ); return _value.get_jfloat(); } jdouble as_jdouble() const { type_check(T_DOUBLE); return _value.get_jdouble(); } @@ -120,7 +121,7 @@ class LIR_Const: public LIR_OprPtr { #endif - jint as_jint_bits() const { type_check(T_FLOAT, T_INT); return _value.get_jint(); } + jint as_jint_bits() const { type_check(T_FLOAT, T_INT, T_ADDRESS); return _value.get_jint(); } jint as_jint_lo_bits() const { if (type() == T_DOUBLE) { return low(jlong_cast(_value.get_jdouble())); @@ -718,6 +719,7 @@ class LIR_OprFact: public AllStatic { static LIR_Opr intptrConst(void* p) { return (LIR_Opr)(new LIR_Const(p)); } static LIR_Opr intptrConst(intptr_t v) { return (LIR_Opr)(new LIR_Const((void*)v)); } static LIR_Opr illegal() { return (LIR_Opr)-1; } + static LIR_Opr addressConst(jint i) { return (LIR_Opr)(new LIR_Const(i, true)); } static LIR_Opr value_type(ValueType* type); static LIR_Opr dummy_value_type(ValueType* type); diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index ab049832121..1012e3c7d6e 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -2479,6 +2479,15 @@ int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArrayappend(new ConstantLongValue(c->as_jint())); +#else + scope_values->append(new ConstantIntValue(c->as_jint())); +#endif + return 1; + } + default: ShouldNotReachHere(); return -1; diff --git a/hotspot/test/compiler/6932496/Test6932496.java b/hotspot/test/compiler/6932496/Test6932496.java new file mode 100644 index 00000000000..2b125e626a1 --- /dev/null +++ b/hotspot/test/compiler/6932496/Test6932496.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6932496 + * @summary incorrect deopt of jsr subroutine on 64 bit c1 + * + * @compile -source 1.5 -target 1.5 -XDjsrlimit=0 Test6932496.java + * @run main/othervm -Xcomp -XX:CompileOnly=Test6932496.m Test6932496 + */ + +public class Test6932496 { + static class A { + volatile boolean flag = false; + } + + static void m() { + try { + } finally { + A a = new A(); + a.flag = true; + } + } + + + static public void main(String[] args) { + m(); + } +} From 8742fc8e628c74c3161d3475fcc2c520352ec7fb Mon Sep 17 00:00:00 2001 From: Xiaobin Lu Date: Wed, 10 Mar 2010 21:42:26 -0800 Subject: [PATCH 21/33] 6933402: RFE: Improve PrintSafepointStatistics output to track cleanup time Improve the usability of safepoint statistics data. See bug evaluation for more details. Reviewed-by: ysr, dholmes --- hotspot/src/share/vm/runtime/safepoint.cpp | 136 ++++++++++++--------- hotspot/src/share/vm/runtime/safepoint.hpp | 26 ++-- 2 files changed, 96 insertions(+), 66 deletions(-) diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index 04a5240d734..ddab8f27313 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -30,8 +30,8 @@ SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized; volatile int SafepointSynchronize::_waiting_to_block = 0; -jlong SafepointSynchronize::_last_safepoint = 0; volatile int SafepointSynchronize::_safepoint_counter = 0; +long SafepointSynchronize::_end_of_last_safepoint = 0; static volatile int PageArmed = 0 ; // safepoint polling page is RO|RW vs PROT_NONE static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only static bool timeout_error_printed = false; @@ -42,7 +42,10 @@ void SafepointSynchronize::begin() { Thread* myThread = Thread::current(); assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint"); - _last_safepoint = os::javaTimeNanos(); + if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) { + _safepoint_begin_time = os::javaTimeNanos(); + _ts_of_current_safepoint = tty->time_stamp().seconds(); + } #ifndef SERIALGC if (UseConcMarkSweepGC) { @@ -320,6 +323,11 @@ void SafepointSynchronize::begin() { // Call stuff that needs to be run when a safepoint is just about to be completed do_cleanup_tasks(); + + if (PrintSafepointStatistics) { + // Record how much time spend on the above cleanup tasks + update_statistics_on_cleanup_end(os::javaTimeNanos()); + } } } @@ -411,6 +419,9 @@ void SafepointSynchronize::end() { ConcurrentGCThread::safepoint_desynchronize(); } #endif // SERIALGC + // record this time so VMThread can keep track how much time has elasped + // since last safepoint. + _end_of_last_safepoint = os::javaTimeMillis(); } bool SafepointSynchronize::is_cleanup_needed() { @@ -445,24 +456,23 @@ void CounterDecay::decay() { // Various cleaning tasks that should be done periodically at safepoints void SafepointSynchronize::do_cleanup_tasks() { - jlong cleanup_time; - - // Update fat-monitor pool, since this is a safepoint. - if (TraceSafepoint) { - cleanup_time = os::javaTimeNanos(); + { + TraceTime t1("deflating idle monitors", TraceSafepoint); + ObjectSynchronizer::deflate_idle_monitors(); + } + + { + TraceTime t2("updating inline caches", TraceSafepoint); + InlineCacheBuffer::update_inline_caches(); } - ObjectSynchronizer::deflate_idle_monitors(); - InlineCacheBuffer::update_inline_caches(); if(UseCounterDecay && CounterDecay::is_decay_needed()) { + TraceTime t3("decaying counter", TraceSafepoint); CounterDecay::decay(); } - NMethodSweeper::sweep(); - if (TraceSafepoint) { - tty->print_cr("do_cleanup_tasks takes "INT64_FORMAT_W(6) "ms", - (os::javaTimeNanos() - cleanup_time) / MICROUNITS); - } + TraceTime t4("sweeping nmethods", TraceSafepoint); + NMethodSweeper::sweep(); } @@ -979,17 +989,32 @@ void ThreadSafepointState::handle_polling_page_exception() { // Statistics & Instrumentations // SafepointSynchronize::SafepointStats* SafepointSynchronize::_safepoint_stats = NULL; +jlong SafepointSynchronize::_safepoint_begin_time = 0; int SafepointSynchronize::_cur_stat_index = 0; julong SafepointSynchronize::_safepoint_reasons[VM_Operation::VMOp_Terminating]; julong SafepointSynchronize::_coalesced_vmop_count = 0; jlong SafepointSynchronize::_max_sync_time = 0; +jlong SafepointSynchronize::_max_vmop_time = 0; +float SafepointSynchronize::_ts_of_current_safepoint = 0.0f; -// last_safepoint_start_time records the start time of last safepoint. -static jlong last_safepoint_start_time = 0; -static jlong sync_end_time = 0; +static jlong cleanup_end_time = 0; static bool need_to_track_page_armed_status = false; static bool init_done = false; +// Helper method to print the header. +static void print_header() { + tty->print(" vmop " + "[threads: total initially_running wait_to_block] "); + tty->print("[time: spin block sync cleanup vmop] "); + + // no page armed status printed out if it is always armed. + if (need_to_track_page_armed_status) { + tty->print("page_armed "); + } + + tty->print_cr("page_trap_count"); +} + void SafepointSynchronize::deferred_initialize_stat() { if (init_done) return; @@ -1016,19 +1041,6 @@ void SafepointSynchronize::deferred_initialize_stat() { if (UseCompilerSafepoints && DeferPollingPageLoopCount >= 0) { need_to_track_page_armed_status = true; } - - tty->print(" vmop_name " - "[threads: total initially_running wait_to_block] "); - tty->print("[time: spin block sync] " - "[vmop_time time_elapsed] "); - - // no page armed status printed out if it is always armed. - if (need_to_track_page_armed_status) { - tty->print("page_armed "); - } - - tty->print_cr("page_trap_count"); - init_done = true; } @@ -1036,6 +1048,8 @@ void SafepointSynchronize::begin_statistics(int nof_threads, int nof_running) { assert(init_done, "safepoint statistics array hasn't been initialized"); SafepointStats *spstat = &_safepoint_stats[_cur_stat_index]; + spstat->_time_stamp = _ts_of_current_safepoint; + VM_Operation *op = VMThread::vm_operation(); spstat->_vmop_type = (op != NULL ? op->type() : -1); if (op != NULL) { @@ -1054,14 +1068,6 @@ void SafepointSynchronize::begin_statistics(int nof_threads, int nof_running) { } else { spstat->_time_to_spin = 0; } - - if (last_safepoint_start_time == 0) { - spstat->_time_elapsed_since_last_safepoint = 0; - } else { - spstat->_time_elapsed_since_last_safepoint = _last_safepoint - - last_safepoint_start_time; - } - last_safepoint_start_time = _last_safepoint; } void SafepointSynchronize::update_statistics_on_spin_end() { @@ -1097,18 +1103,31 @@ void SafepointSynchronize::update_statistics_on_sync_end(jlong end_time) { // Records the end time of sync which will be used to calculate the total // vm operation time. Again, the real time spending in syncing will be deducted // from the start of the sync time later when end_statistics is called. - spstat->_time_to_sync = end_time - _last_safepoint; + spstat->_time_to_sync = end_time - _safepoint_begin_time; if (spstat->_time_to_sync > _max_sync_time) { _max_sync_time = spstat->_time_to_sync; } - sync_end_time = end_time; + + spstat->_time_to_do_cleanups = end_time; +} + +void SafepointSynchronize::update_statistics_on_cleanup_end(jlong end_time) { + SafepointStats *spstat = &_safepoint_stats[_cur_stat_index]; + + // Record how long spent in cleanup tasks. + spstat->_time_to_do_cleanups = end_time - spstat->_time_to_do_cleanups; + + cleanup_end_time = end_time; } void SafepointSynchronize::end_statistics(jlong vmop_end_time) { SafepointStats *spstat = &_safepoint_stats[_cur_stat_index]; // Update the vm operation time. - spstat->_time_to_exec_vmop = vmop_end_time - sync_end_time; + spstat->_time_to_exec_vmop = vmop_end_time - cleanup_end_time; + if (spstat->_time_to_exec_vmop > _max_vmop_time) { + _max_vmop_time = spstat->_time_to_exec_vmop; + } // Only the sync time longer than the specified // PrintSafepointStatisticsTimeout will be printed out right away. // By default, it is -1 meaning all samples will be put into the list. @@ -1119,40 +1138,42 @@ void SafepointSynchronize::end_statistics(jlong vmop_end_time) { } else { // The safepoint statistics will be printed out when the _safepoin_stats // array fills up. - if (_cur_stat_index != PrintSafepointStatisticsCount - 1) { - _cur_stat_index ++; - } else { + if (_cur_stat_index == PrintSafepointStatisticsCount - 1) { print_statistics(); _cur_stat_index = 0; - tty->print_cr(""); + } else { + _cur_stat_index++; } } } void SafepointSynchronize::print_statistics() { - int index; SafepointStats* sstats = _safepoint_stats; - for (index = 0; index <= _cur_stat_index; index++) { + for (int index = 0; index <= _cur_stat_index; index++) { + if (index % 30 == 0) { + print_header(); + } sstats = &_safepoint_stats[index]; - tty->print("%-28s [" + tty->print("%.3f: ", sstats->_time_stamp); + tty->print("%-26s [" INT32_FORMAT_W(8)INT32_FORMAT_W(11)INT32_FORMAT_W(15) - "] ", + " ] ", sstats->_vmop_type == -1 ? "no vm operation" : VM_Operation::name(sstats->_vmop_type), sstats->_nof_total_threads, sstats->_nof_initial_running_threads, sstats->_nof_threads_wait_to_block); // "/ MICROUNITS " is to convert the unit from nanos to millis. - tty->print(" [" - INT64_FORMAT_W(6)INT64_FORMAT_W(6)INT64_FORMAT_W(6) - "] " - "["INT64_FORMAT_W(6)INT64_FORMAT_W(9) "] ", + tty->print(" [" + INT64_FORMAT_W(6)INT64_FORMAT_W(6) + INT64_FORMAT_W(6)INT64_FORMAT_W(6) + INT64_FORMAT_W(6)" ] ", sstats->_time_to_spin / MICROUNITS, sstats->_time_to_wait_to_block / MICROUNITS, sstats->_time_to_sync / MICROUNITS, - sstats->_time_to_exec_vmop / MICROUNITS, - sstats->_time_elapsed_since_last_safepoint / MICROUNITS); + sstats->_time_to_do_cleanups / MICROUNITS, + sstats->_time_to_exec_vmop / MICROUNITS); if (need_to_track_page_armed_status) { tty->print(INT32_FORMAT" ", sstats->_page_armed); @@ -1174,7 +1195,7 @@ void SafepointSynchronize::print_stat_on_exit() { // don't print it out. // Approximate the vm op time. _safepoint_stats[_cur_stat_index]._time_to_exec_vmop = - os::javaTimeNanos() - sync_end_time; + os::javaTimeNanos() - cleanup_end_time; if ( PrintSafepointStatisticsTimeout < 0 || spstat->_time_to_sync > PrintSafepointStatisticsTimeout * MICROUNITS) { @@ -1203,6 +1224,9 @@ void SafepointSynchronize::print_stat_on_exit() { _coalesced_vmop_count); tty->print_cr("Maximum sync time "INT64_FORMAT_W(5)" ms", _max_sync_time / MICROUNITS); + tty->print_cr("Maximum vm operation time (except for Exit VM operation) " + INT64_FORMAT_W(5)" ms", + _max_vmop_time / MICROUNITS); } // ------------------------------------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/runtime/safepoint.hpp b/hotspot/src/share/vm/runtime/safepoint.hpp index 86b16e7e0d7..c7db5fa0070 100644 --- a/hotspot/src/share/vm/runtime/safepoint.hpp +++ b/hotspot/src/share/vm/runtime/safepoint.hpp @@ -65,6 +65,7 @@ class SafepointSynchronize : AllStatic { }; typedef struct { + float _time_stamp; // record when the current safepoint occurs in seconds int _vmop_type; // type of VM operation triggers the safepoint int _nof_total_threads; // total number of Java threads int _nof_initial_running_threads; // total number of initially seen running threads @@ -73,14 +74,14 @@ class SafepointSynchronize : AllStatic { int _nof_threads_hit_page_trap; // total number of threads hitting the page trap jlong _time_to_spin; // total time in millis spent in spinning jlong _time_to_wait_to_block; // total time in millis spent in waiting for to block + jlong _time_to_do_cleanups; // total time in millis spent in performing cleanups jlong _time_to_sync; // total time in millis spent in getting to _synchronized jlong _time_to_exec_vmop; // total time in millis spent in vm operation itself - jlong _time_elapsed_since_last_safepoint; // time elasped since last safepoint } SafepointStats; private: static volatile SynchronizeState _state; // Threads might read this flag directly, without acquireing the Threads_lock - static volatile int _waiting_to_block; // No. of threads we are waiting for to block. + static volatile int _waiting_to_block; // number of threads we are waiting for to block // This counter is used for fast versions of jni_GetField. // An even value means there is no ongoing safepoint operations. @@ -91,19 +92,22 @@ class SafepointSynchronize : AllStatic { public: static volatile int _safepoint_counter; private: - - static jlong _last_safepoint; // Time of last safepoint + static long _end_of_last_safepoint; // Time of last safepoint in milliseconds // statistics - static SafepointStats* _safepoint_stats; // array of SafepointStats struct - static int _cur_stat_index; // current index to the above array - static julong _safepoint_reasons[]; // safepoint count for each VM op - static julong _coalesced_vmop_count;// coalesced vmop count - static jlong _max_sync_time; // maximum sync time in nanos + static jlong _safepoint_begin_time; // time when safepoint begins + static SafepointStats* _safepoint_stats; // array of SafepointStats struct + static int _cur_stat_index; // current index to the above array + static julong _safepoint_reasons[]; // safepoint count for each VM op + static julong _coalesced_vmop_count; // coalesced vmop count + static jlong _max_sync_time; // maximum sync time in nanos + static jlong _max_vmop_time; // maximum vm operation time in nanos + static float _ts_of_current_safepoint; // time stamp of current safepoint in seconds static void begin_statistics(int nof_threads, int nof_running); static void update_statistics_on_spin_end(); static void update_statistics_on_sync_end(jlong end_time); + static void update_statistics_on_cleanup_end(jlong end_time); static void end_statistics(jlong end_time); static void print_statistics(); inline static void inc_page_trap_count() { @@ -140,7 +144,9 @@ public: static void handle_polling_page_exception(JavaThread *thread); // VM Thread interface for determining safepoint rate - static long last_non_safepoint_interval() { return os::javaTimeMillis() - _last_safepoint; } + static long last_non_safepoint_interval() { + return os::javaTimeMillis() - _end_of_last_safepoint; + } static bool is_cleanup_needed(); static void do_cleanup_tasks(); From dae3356905a42eb8bf35d6061c1f43181b79adcd Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Thu, 11 Mar 2010 05:09:20 -0800 Subject: [PATCH 22/33] 6934089: Zero 32-bit/64kb page fix The fix for 6927165 increased the number of shadow pages for 32-bit platforms and this causes a problem on systems with 64kb pages. Reviewed-by: twisti --- hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp index 5c6587a0823..66666ac8092 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,10 @@ // define_pd_global(bool, DontYieldALot, false); -#ifdef _LP64 define_pd_global(intx, ThreadStackSize, 1536); +#ifdef _LP64 define_pd_global(intx, VMThreadStackSize, 1024); #else -define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, VMThreadStackSize, 512); #endif // _LP64 define_pd_global(intx, SurvivorRatio, 8); From 82e9e2b4af2fb50e97fc6366620295006fef90cd Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 16 Mar 2010 11:52:17 +0100 Subject: [PATCH 23/33] 6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob Passing a null pointer to an InvokeDynamic function call should lead to a NullPointerException. Reviewed-by: kvn, never --- .../src/cpu/sparc/vm/stubRoutines_sparc.hpp | 11 +++- .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 10 ---- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 10 ---- .../src/cpu/x86/vm/stubRoutines_x86_32.hpp | 7 ++- .../src/cpu/x86/vm/stubRoutines_x86_64.hpp | 16 ++--- hotspot/src/share/vm/code/codeBlob.cpp | 46 +++++++++++++-- hotspot/src/share/vm/code/codeBlob.hpp | 59 +++++++++++++++---- hotspot/src/share/vm/includeDB_core | 2 + hotspot/src/share/vm/prims/methodHandles.cpp | 41 ++++++++++++- hotspot/src/share/vm/prims/methodHandles.hpp | 20 ++++++- hotspot/src/share/vm/runtime/init.cpp | 5 +- .../src/share/vm/runtime/sharedRuntime.cpp | 11 ++-- .../src/share/vm/runtime/sharedRuntime.hpp | 3 - 13 files changed, 182 insertions(+), 59 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp index 6b23258ffa2..b3a2618d083 100644 --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,13 @@ static bool returns_to_call_stub(address return_pc) { enum /* platform_dependent_constants */ { // %%%%%%%% May be able to shrink this a lot - code_size1 = 20000, // simply increase if too small (assembler will crash if too small) - code_size2 = 20000 // simply increase if too small (assembler will crash if too small) + code_size1 = 20000, // simply increase if too small (assembler will crash if too small) + code_size2 = 20000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 }; class Sparc { diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index e8276e5188f..1d971931940 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -2276,16 +2276,6 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 516a7826a92..5417eb160cb 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3009,16 +3009,6 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp index 57e75534fce..9fa4b048f1b 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ enum platform_dependent_constants { code_size2 = 22000 // simply increase if too small (assembler will crash if too small) }; +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 +}; + class x86 { friend class StubGenerator; friend class VMStructs; diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp index 7cf06f479ff..6772eb3babb 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,12 +28,14 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; } -enum platform_dependent_constants -{ - code_size1 = 19000, // simply increase if too small (assembler will - // crash if too small) - code_size2 = 22000 // simply increase if too small (assembler will - // crash if too small) +enum platform_dependent_constants { + code_size1 = 19000, // simply increase if too small (assembler will crash if too small) + code_size2 = 22000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 13000 }; class x86 { diff --git a/hotspot/src/share/vm/code/codeBlob.cpp b/hotspot/src/share/vm/code/codeBlob.cpp index 4ccc377a308..d8471b98f1f 100644 --- a/hotspot/src/share/vm/code/codeBlob.cpp +++ b/hotspot/src/share/vm/code/codeBlob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,7 +249,6 @@ BufferBlob* BufferBlob::create(const char* name, int buffer_size) { size += round_to(buffer_size, oopSize); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size); } @@ -271,7 +270,6 @@ BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { unsigned int size = allocation_size(cb, sizeof(BufferBlob)); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size, cb); } @@ -298,10 +296,48 @@ void BufferBlob::free( BufferBlob *blob ) { MemoryService::track_code_cache_memory_usage(); } -bool BufferBlob::is_adapter_blob() const { - return (strcmp(AdapterHandlerEntry::name, name()) == 0); + +//---------------------------------------------------------------------------------------------------- +// Implementation of AdapterBlob + +AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + AdapterBlob* blob = NULL; + unsigned int size = allocation_size(cb, sizeof(AdapterBlob)); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) AdapterBlob(size, cb); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; } + +//---------------------------------------------------------------------------------------------------- +// Implementation of MethodHandlesAdapterBlob + +MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + MethodHandlesAdapterBlob* blob = NULL; + unsigned int size = sizeof(MethodHandlesAdapterBlob); + // align the size to CodeEntryAlignment + size = align_code_offset(size); + size += round_to(buffer_size, oopSize); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) MethodHandlesAdapterBlob(size); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; +} + + //---------------------------------------------------------------------------------------------------- // Implementation of RuntimeStub diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index bbd430a14c6..0c9e43c8422 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,14 +90,15 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { void flush(); // Typing - virtual bool is_buffer_blob() const { return false; } - virtual bool is_nmethod() const { return false; } - virtual bool is_runtime_stub() const { return false; } - virtual bool is_deoptimization_stub() const { return false; } - virtual bool is_uncommon_trap_stub() const { return false; } - virtual bool is_exception_stub() const { return false; } - virtual bool is_safepoint_stub() const { return false; } - virtual bool is_adapter_blob() const { return false; } + virtual bool is_buffer_blob() const { return false; } + virtual bool is_nmethod() const { return false; } + virtual bool is_runtime_stub() const { return false; } + virtual bool is_deoptimization_stub() const { return false; } + virtual bool is_uncommon_trap_stub() const { return false; } + virtual bool is_exception_stub() const { return false; } + virtual bool is_safepoint_stub() const { return false; } + virtual bool is_adapter_blob() const { return false; } + virtual bool is_method_handles_adapter_blob() const { return false; } virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c1() const { return false; } @@ -221,6 +222,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { class BufferBlob: public CodeBlob { friend class VMStructs; + friend class AdapterBlob; + friend class MethodHandlesAdapterBlob; + private: // Creation support BufferBlob(const char* name, int size); @@ -236,8 +240,7 @@ class BufferBlob: public CodeBlob { static void free(BufferBlob* buf); // Typing - bool is_buffer_blob() const { return true; } - bool is_adapter_blob() const; + virtual bool is_buffer_blob() const { return true; } // GC/Verification support void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ } @@ -254,6 +257,40 @@ class BufferBlob: public CodeBlob { }; +//---------------------------------------------------------------------------------------------------- +// AdapterBlob: used to hold C2I/I2C adapters + +class AdapterBlob: public BufferBlob { +private: + AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {} + AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {} + +public: + // Creation + static AdapterBlob* create(CodeBuffer* cb); + + // Typing + virtual bool is_adapter_blob() const { return true; } +}; + + +//---------------------------------------------------------------------------------------------------- +// MethodHandlesAdapterBlob: used to hold MethodHandles adapters + +class MethodHandlesAdapterBlob: public BufferBlob { +private: + MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {} + MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {} + +public: + // Creation + static MethodHandlesAdapterBlob* create(int buffer_size); + + // Typing + virtual bool is_method_handles_adapter_blob() const { return true; } +}; + + //---------------------------------------------------------------------------------------------------- // RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 557db70983b..c0dec44d773 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2017,6 +2017,7 @@ init.cpp handles.inline.hpp init.cpp icBuffer.hpp init.cpp icache.hpp init.cpp init.hpp +init.cpp methodHandles.hpp init.cpp safepoint.hpp init.cpp sharedRuntime.hpp init.cpp universe.hpp @@ -2871,6 +2872,7 @@ methodHandles.cpp methodHandles.hpp methodHandles.cpp oopFactory.hpp methodHandles.cpp reflection.hpp methodHandles.cpp signature.hpp +methodHandles.cpp stubRoutines.hpp methodHandles.cpp symbolTable.hpp methodHandles_.cpp allocation.inline.hpp diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 038bb2fa55a..4131f0f34b8 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,10 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { NULL }; +// Adapters. +MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL; +int MethodHandles::_adapter_code_size = StubRoutines::method_handles_adapters_code_size; + jobject MethodHandles::_raise_exception_method; #ifdef ASSERT @@ -95,6 +99,41 @@ bool MethodHandles::spot_check_entry_names() { } #endif + +//------------------------------------------------------------------------------ +// MethodHandles::generate_adapters +// +void MethodHandles::generate_adapters() { + if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; + + assert(_adapter_code == NULL, "generate only once"); + + ResourceMark rm; + TraceTime timer("MethodHandles adapters generation", TraceStartupTime); + _adapter_code = MethodHandlesAdapterBlob::create(_adapter_code_size); + if (_adapter_code == NULL) + vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); + CodeBuffer code(_adapter_code->instructions_begin(), _adapter_code->instructions_size()); + + MethodHandlesAdapterGenerator g(&code); + g.generate(); +} + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator::generate +// +void MethodHandlesAdapterGenerator::generate() { + // Generate generic method handle adapters. + for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; + ek < MethodHandles::_EK_LIMIT; + ek = MethodHandles::EntryKind(1 + (int)ek)) { + StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); + MethodHandles::generate_method_handle_stub(_masm, ek); + } +} + + void MethodHandles::set_enabled(bool z) { if (_enabled != z) { guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index fea29650b5c..1bbf82c41ec 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -115,6 +115,10 @@ class MethodHandles: AllStatic { static const char* _entry_names[_EK_LIMIT+1]; static jobject _raise_exception_method; + // Adapters. + static MethodHandlesAdapterBlob* _adapter_code; + static int _adapter_code_size; + static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } @@ -230,7 +234,10 @@ class MethodHandles: AllStatic { // bit values for suppress argument to expand_MemberName: enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; - // called from InterpreterGenerator and StubGenerator + // Generate MethodHandles adapters. + static void generate_adapters(); + + // Called from InterpreterGenerator and MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); @@ -447,3 +454,14 @@ class MethodHandleEntry { address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); } address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); } + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator +// +class MethodHandlesAdapterGenerator : public StubCodeGenerator { +public: + MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} + + void generate(); +}; diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index 3f470e3ed9a..0ab624e691d 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,6 +118,9 @@ jint init_globals() { javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init + // Generate MethodHandles adapters. + MethodHandles::generate_adapters(); + // Although we'd like to, we can't easily do a heap verify // here because the main thread isn't yet a JavaThread, so // its TLAB may not be made parseable from the usual interfaces. diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 0e465e46cbe..d09579b7709 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -582,7 +582,7 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, // 3. Implict null exception in nmethod if (!cb->is_nmethod()) { - guarantee(cb->is_adapter_blob(), + guarantee(cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(), "exception happened outside interpreter, nmethods and vtable stubs (1)"); // There is no handler here, so we will simply unwind. return StubRoutines::throw_NullPointerException_at_call_entry(); @@ -2079,7 +2079,6 @@ class AdapterHandlerTableIterator : public StackObj { // --------------------------------------------------------------------------- // Implementation of AdapterHandlerLibrary -const char* AdapterHandlerEntry::name = "I2C/C2I adapters"; AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL; const int AdapterHandlerLibrary_size = 16*K; @@ -2131,7 +2130,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { ResourceMark rm; NOT_PRODUCT(int code_size); - BufferBlob *B = NULL; + AdapterBlob* B = NULL; AdapterHandlerEntry* entry = NULL; AdapterFingerPrint* fingerprint = NULL; { @@ -2181,7 +2180,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { // Create I2C & C2I handlers - BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache + BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { CodeBuffer buffer(buf->instructions_begin(), buf->instructions_size()); short buffer_locs[20]; @@ -2210,7 +2209,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { } #endif - B = BufferBlob::create(AdapterHandlerEntry::name, &buffer); + B = AdapterBlob::create(&buffer); NOT_PRODUCT(code_size = buffer.code_size()); } if (B == NULL) { @@ -2242,7 +2241,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { jio_snprintf(blob_id, sizeof(blob_id), "%s(%s)@" PTR_FORMAT, - AdapterHandlerEntry::name, + B->name(), fingerprint->as_string(), B->instructions_begin()); VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end()); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index a540065c20d..c2348c22022 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -567,9 +567,6 @@ class AdapterHandlerEntry : public BasicHashtableEntry { AdapterHandlerEntry(); public: - // The name we give all buffer blobs - static const char* name; - address get_i2c_entry() { return _i2c_entry; } address get_c2i_entry() { return _c2i_entry; } address get_c2i_unverified_entry() { return _c2i_unverified_entry; } From e8191b6730006996eac2809fa650c68c88cbbd6c Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 16 Mar 2010 15:35:33 -0700 Subject: [PATCH 24/33] 6935466: new CodeCache flushing code is not guarded by the flag Add missing guard. Reviewed-by: never --- hotspot/src/share/vm/compiler/compileBroker.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index c3173c9290c..6e519ec14a4 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -988,10 +988,12 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, } if (method->is_not_compilable(comp_level)) return NULL; - nmethod* saved = CodeCache::find_and_remove_saved_code(method()); - if (saved != NULL) { - method->set_code(method, saved); - return saved; + if (UseCodeCacheFlushing) { + nmethod* saved = CodeCache::find_and_remove_saved_code(method()); + if (saved != NULL) { + method->set_code(method, saved); + return saved; + } } } else { From ebc298d208118b43d3c73bc3dfae36df8383c59a Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 17 Mar 2010 10:22:41 +0100 Subject: [PATCH 25/33] 6934966: JSR 292 add C1 logic for saved SP over MethodHandle calls The logic for x86 C1 to save the SP over MH calls is pretty straight forward but SPARC handles that differently. Reviewed-by: never, jrose --- hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp | 5 ++++- hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 4 ++-- hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp | 5 ++++- hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 8 ++++---- hotspot/src/share/vm/c1/c1_LIR.cpp | 1 + hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 4 ++-- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 5 +++-- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp index 2651784469a..81b97983220 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,3 +143,6 @@ static bool is_caller_save_register (LIR_Opr reg); static bool is_caller_save_register (Register r); + + // JSR 292 + static LIR_Opr& method_handle_invoke_SP_save_opr() { return L7_opr; } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 05804c52d7a..3fe53ae890f 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -712,12 +712,12 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { } -void LIR_Assembler::preserve_SP() { +void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { Unimplemented(); } -void LIR_Assembler::restore_SP() { +void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { Unimplemented(); } diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp index 65671c32d4a..110dedd7c52 100644 --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,3 +126,6 @@ assert(i >= 0 && i < nof_caller_save_xmm_regs, "out of bounds"); return _caller_save_xmm_regs[i]; } + + // JSR 292 + static LIR_Opr& method_handle_invoke_SP_save_opr() { return rbp_opr; } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index eb1ee51bd82..987a9de7d33 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -2762,13 +2762,13 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { } -void LIR_Assembler::preserve_SP() { - __ movptr(rbp, rsp); +void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { + __ movptr(FrameMap::method_handle_invoke_SP_save_opr()->as_register(), rsp); } -void LIR_Assembler::restore_SP() { - __ movptr(rsp, rbp); +void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { + __ movptr(rsp, FrameMap::method_handle_invoke_SP_save_opr()->as_register()); } diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index ce8efb9b413..4d9f6958a26 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -705,6 +705,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { } if (opJavaCall->_info) do_info(opJavaCall->_info); + if (opJavaCall->is_method_handle_invoke()) do_temp(FrameMap::method_handle_invoke_SP_save_opr()); do_call(); if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result); diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index a58051f1a33..14c4485e343 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -416,7 +416,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { // JSR 292 // Preserve the SP over MethodHandle call sites. if (op->is_method_handle_invoke()) { - preserve_SP(); + preserve_SP(op); } if (os::is_MP()) { @@ -445,7 +445,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { } if (op->is_method_handle_invoke()) { - restore_SP(); + restore_SP(op); } #if defined(X86) && defined(TIERED) diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 01de986d8a9..a7c1ecc869e 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -209,8 +209,9 @@ class LIR_Assembler: public CompilationResourceObj { void ic_call( LIR_OpJavaCall* op); void vtable_call( LIR_OpJavaCall* op); - void preserve_SP(); - void restore_SP(); + // JSR 292 + void preserve_SP(LIR_OpJavaCall* op); + void restore_SP( LIR_OpJavaCall* op); void osr_entry(); From 72a7a6ffcf16c1b434f2d44d4d0a2a83c027862e Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 17 Mar 2010 10:47:03 -0700 Subject: [PATCH 26/33] 6935535: String.indexOf() returns incorrect result on x86 with SSE4.2 Added missing counter decrement when substring search restarted. Reviewed-by: twisti --- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 1 + hotspot/test/compiler/6935535/Test.java | 48 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 hotspot/test/compiler/6935535/Test.java diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index c22a8c1d01a..f85c0c49a66 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -8460,6 +8460,7 @@ void MacroAssembler::string_indexof(Register str1, Register str2, subptr(str1, result); // Restore counter shrl(str1, 1); addl(cnt1, str1); + decrementl(cnt1); lea(str1, Address(result, 2)); // Reload string // Load substr diff --git a/hotspot/test/compiler/6935535/Test.java b/hotspot/test/compiler/6935535/Test.java new file mode 100644 index 00000000000..8b6b67f328a --- /dev/null +++ b/hotspot/test/compiler/6935535/Test.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6935535 + * @summary String.indexOf() returns incorrect result on x86 with SSE4.2 + * + * @run main/othervm -Xcomp Test + */ + +public class Test { + + static int IndexOfTest(String str) { + return str.indexOf("1111111111111xx1x"); + } + + public static void main(String args[]) { + String str = "1111111111111xx1111111111111xx1x"; + str = str.substring(0, 31); + int idx = IndexOfTest(str); + System.out.println("IndexOf(" + "1111111111111xx1x" + ") = " + idx + " in " + str); + if (idx != -1) { + System.exit(97); + } + } +} + From dac78c30b9d3cda1a7849f21de998c94e9724919 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 17 Mar 2010 16:40:25 -0700 Subject: [PATCH 27/33] 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I Reviewed-by: kvn --- hotspot/src/share/vm/opto/loopTransform.cpp | 176 +++++++++++------- hotspot/src/share/vm/opto/loopnode.hpp | 2 +- .../test/compiler/6930043/Test6930043.java | 76 ++++++++ 3 files changed, 184 insertions(+), 70 deletions(-) create mode 100644 hotspot/test/compiler/6930043/Test6930043.java diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index daa3ceca869..522aa2da388 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2088,29 +2088,41 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, int scale, Node* offset, Node* init, Node* limit, Node* stride, - Node* range) { + Node* range, bool upper) { + DEBUG_ONLY(ttyLocker ttyl); + if (TraceLoopPredicate) tty->print("rc_predicate "); + Node* max_idx_expr = init; int stride_con = stride->get_int(); - if ((stride_con > 0) == (scale > 0)) { + if ((stride_con > 0) == (scale > 0) == upper) { max_idx_expr = new (C, 3) SubINode(limit, stride); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) tty->print("(limit - stride) "); + } else { + if (TraceLoopPredicate) tty->print("init "); } if (scale != 1) { ConNode* con_scale = _igvn.intcon(scale); max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) tty->print("* %d ", scale); } if (offset && (!offset->is_Con() || offset->get_int() != 0)){ max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) + if (offset->is_Con()) tty->print("+ %d ", offset->get_int()); + else tty->print("+ offset "); } CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range); register_new_node(cmp, ctrl); BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt); register_new_node(bol, ctrl); + + if (TraceLoopPredicate) tty->print_cr(" 0) { // Following are changed to nonnull when a predicate can be hoisted ProjNode* new_predicate_proj = NULL; - BoolNode* new_predicate_bol = NULL; ProjNode* proj = if_proj_list.pop()->as_Proj(); IfNode* iff = proj->in(0)->as_If(); @@ -2218,93 +2229,120 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { // Invariant test new_predicate_proj = create_new_if_for_predicate(predicate_proj); Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); - new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); - if (TraceLoopPredicate) tty->print("invariant"); + BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); + + // Negate test if necessary + bool negated = false; + if (proj->_con != predicate_proj->_con) { + new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); + register_new_node(new_predicate_bol, ctrl); + negated = true; + } + IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); + _igvn.hash_delete(new_predicate_iff); + new_predicate_iff->set_req(1, new_predicate_bol); + if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx); + } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { - // Range check (only for counted loops) - new_predicate_proj = create_new_if_for_predicate(predicate_proj); - Node *ctrl = new_predicate_proj->in(0)->as_If()->in(0); + assert(proj->_con == predicate_proj->_con, "must match"); + + // Range check for counted loops const Node* cmp = bol->in(1)->as_Cmp(); Node* idx = cmp->in(1); assert(!invar.is_invariant(idx), "index is variant"); assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be"); - LoadRangeNode* ld_rng = (LoadRangeNode*)cmp->in(2); // LoadRangeNode + Node* ld_rng = cmp->in(2); // LoadRangeNode assert(invar.is_invariant(ld_rng), "load range must be invariant"); - ld_rng = (LoadRangeNode*)invar.clone(ld_rng, ctrl); int scale = 1; Node* offset = zero; bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset); assert(ok, "must be index expression"); + + Node* init = cl->init_trip(); + Node* limit = cl->limit(); + Node* stride = cl->stride(); + + // Build if's for the upper and lower bound tests. The + // lower_bound test will dominate the upper bound test and all + // cloned or created nodes will use the lower bound test as + // their declared control. + ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj); + ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj); + assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); + Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); + + // Perform cloning to keep Invariance state correct since the + // late schedule will place invariant things in the loop. + ld_rng = invar.clone(ld_rng, ctrl); if (offset && offset != zero) { assert(invar.is_invariant(offset), "offset must be loop invariant"); offset = invar.clone(offset, ctrl); } - Node* init = cl->init_trip(); - Node* limit = cl->limit(); - Node* stride = cl->stride(); - new_predicate_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng); - if (TraceLoopPredicate) tty->print("range check"); - } - if (new_predicate_proj == NULL) { + // Test the lower bound + Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, false); + IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); + _igvn.hash_delete(lower_bound_iff); + lower_bound_iff->set_req(1, lower_bound_bol); + if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); + + // Test the upper bound + Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, true); + IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); + _igvn.hash_delete(upper_bound_iff); + upper_bound_iff->set_req(1, upper_bound_bol); + if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); + + // Fall through into rest of the clean up code which will move + // any dependent nodes onto the upper bound test. + new_predicate_proj = upper_bound_proj; + } else { // The other proj of the "iff" is a uncommon trap projection, and we can assume // the other proj will not be executed ("executed" means uct raised). continue; - } else { - // Success - attach condition (new_predicate_bol) to predicate if - invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate - IfNode* new_iff = new_predicate_proj->in(0)->as_If(); - - // Negate test if necessary - if (proj->_con != predicate_proj->_con) { - new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); - register_new_node(new_predicate_bol, new_iff->in(0)); - if (TraceLoopPredicate) tty->print_cr(" if negated: %d", iff->_idx); - } else { - if (TraceLoopPredicate) tty->print_cr(" if: %d", iff->_idx); - } - - _igvn.hash_delete(new_iff); - new_iff->set_req(1, new_predicate_bol); - - _igvn.hash_delete(iff); - iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); - - Node* ctrl = new_predicate_proj; // new control - ProjNode* dp = proj; // old control - assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj"); - // Find nodes (depends only on the test) off the surviving projection; - // move them outside the loop with the control of proj_clone - for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { - Node* cd = dp->fast_out(i); // Control-dependent node - if (cd->depends_only_on_test()) { - assert(cd->in(0) == dp, ""); - _igvn.hash_delete(cd); - cd->set_req(0, ctrl); // ctrl, not NULL - set_early_ctrl(cd); - _igvn._worklist.push(cd); - IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); - if (new_loop != loop) { - if (!loop->_child) loop->_body.yank(cd); - if (!new_loop->_child ) new_loop->_body.push(cd); - } - --i; - --imax; - } - } - - hoisted = true; - C->set_major_progress(); } + + // Success - attach condition (new_predicate_bol) to predicate if + invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate + + // Eliminate the old if in the loop body + _igvn.hash_delete(iff); + iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); + + Node* ctrl = new_predicate_proj; // new control + ProjNode* dp = proj; // old control + assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj"); + // Find nodes (depends only on the test) off the surviving projection; + // move them outside the loop with the control of proj_clone + for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { + Node* cd = dp->fast_out(i); // Control-dependent node + if (cd->depends_only_on_test()) { + assert(cd->in(0) == dp, ""); + _igvn.hash_delete(cd); + cd->set_req(0, ctrl); // ctrl, not NULL + set_early_ctrl(cd); + _igvn._worklist.push(cd); + IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); + if (new_loop != loop) { + if (!loop->_child) loop->_body.yank(cd); + if (!new_loop->_child ) new_loop->_body.push(cd); + } + --i; + --imax; + } + } + + hoisted = true; + C->set_major_progress(); } // end while #ifndef PRODUCT - // report that the loop predication has been actually performed - // for this loop - if (TraceLoopPredicate && hoisted) { - tty->print("Loop Predication Performed:"); - loop->dump_head(); - } + // report that the loop predication has been actually performed + // for this loop + if (TraceLoopPredicate && hoisted) { + tty->print("Loop Predication Performed:"); + loop->dump_head(); + } #endif return hoisted; diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index e34cfcb18a3..5b09c05ba6a 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -821,7 +821,7 @@ public: BoolNode* rc_predicate(Node* ctrl, int scale, Node* offset, Node* init, Node* limit, Node* stride, - Node* range); + Node* range, bool upper); // Implementation of the loop predication to promote checks outside the loop bool loop_predication_impl(IdealLoopTree *loop); diff --git a/hotspot/test/compiler/6930043/Test6930043.java b/hotspot/test/compiler/6930043/Test6930043.java new file mode 100644 index 00000000000..3d5061797b8 --- /dev/null +++ b/hotspot/test/compiler/6930043/Test6930043.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6930043 + * @summary C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I + * + * @run main Test6930043 + */ + +import java.io.PrintStream; + +public class Test6930043 { + int[] a; + int idx; + + public int loop_back(int i, int i_0_) { + int i_1_ = 0; + int[] is = a; + if (is == null) return 0; + for (int i_2_ = i; i_2_ >= i_0_; i_2_--) + i_1_ += is[idx = i_2_]; + return i_1_; + } + + public int loop_forw(int start, int end) { + int result = 0; + int[] is = a; + if (is == null) return 0; + for (int index = start; index < end; index++) + result += is[index]; + // result += is[idx = index]; + return result; + } + + public static void main(String[] strings) { + Test6930043 var_Test6930043 = new Test6930043(); + var_Test6930043.a = new int[1000000]; + var_Test6930043.loop_forw(10, 999990); + var_Test6930043.loop_forw(10, 999990); + for (int i = 0; i < 3; i++) { + try { + if (var_Test6930043.loop_forw(-1, 999990) != 0) throw new InternalError(); + } catch (ArrayIndexOutOfBoundsException e) { } + } + var_Test6930043.loop_back(999990, 10); + var_Test6930043.loop_back(999990, 10); + for (int i = 0; i < 3; i++) { + try { + if (var_Test6930043.loop_back(999990, -1) != 0) throw new InternalError(); + } catch (ArrayIndexOutOfBoundsException e) { } + } + } +} From 1270c6c005242d06cda5bd7576ad71d5941c7955 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 18 Mar 2010 09:56:51 +0100 Subject: [PATCH 28/33] 6932091: JSR 292 x86 code cleanup Some code cleanups found during the JSR 292 SPARC port. Reviewed-by: kvn, never --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 114 +++--------------- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 10 +- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 10 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 3 +- hotspot/src/share/vm/prims/methodHandles.hpp | 47 +++++++- hotspot/src/share/vm/runtime/arguments.cpp | 6 + 6 files changed, 72 insertions(+), 118 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 5e168c82bdf..e09986932c7 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -60,13 +60,13 @@ MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _mas } #ifdef ASSERT -static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, +static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, const char* error_message) { // Verify that argslot lies within (rsp, rbp]. Label L_ok, L_bad; - __ cmpptr(rax_argslot, rbp); + __ cmpptr(argslot_reg, rbp); __ jccb(Assembler::above, L_bad); - __ cmpptr(rsp, rax_argslot); + __ cmpptr(rsp, argslot_reg); __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop(error_message); @@ -178,22 +178,6 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, // Now move the argslot down, to point to the opened-up space. __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); - - if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) { - // The caller has specified a bitmask of tags to put into the opened space. - // This only works when the arg_slots value is an assembly-time constant. - int constant_arg_slots = arg_slots.as_constant() / stack_move_unit(); - int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); - for (int slot = 0; slot < constant_arg_slots; slot++) { - BasicType slot_type = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT); - int slot_offset = Interpreter::stackElementSize() * slot; - Address tag_addr(rax_argslot, slot_offset + tag_offset); - __ movptr(tag_addr, frame::tag_for_basic_type(slot_type)); - } - // Note that the new argument slots are tagged properly but contain - // garbage at this point. The value portions must be initialized - // by the caller. (Especially references!) - } } // Helper to remove argument slots from the stack. @@ -206,18 +190,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); #ifdef ASSERT - { - // Verify that [argslot..argslot+size) lies within (rsp, rbp). - Label L_ok, L_bad; - __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); - __ cmpptr(rbx_temp, rbp); - __ jccb(Assembler::above, L_bad); - __ cmpptr(rsp, rax_argslot); - __ jccb(Assembler::below, L_ok); - __ bind(L_bad); - __ stop("deleted argument(s) must fall within current frame"); - __ bind(L_ok); - } + // Verify that [argslot..argslot+size) lies within (rsp, rbp). + __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); + verify_argslot(_masm, rbx_temp, "deleted argument(s) must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); @@ -321,12 +296,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() ); Address vmarg; // __ argument_address(vmargslot) - int tag_offset = -1; - if (TaggedStackInterpreter) { - tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); - assert(tag_offset = wordSize, "stack grows as expected"); - } - const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); if (have_entry(ek)) { @@ -372,11 +341,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ mov(rsp, rsi); // cut the stack back to where the caller started // Repush the arguments as if coming from the interpreter. - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT)); __ push(rdx_code); - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); __ push(rcx_fail); - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); __ push(rax_want); Register rbx_method = rbx_temp; @@ -397,7 +363,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Do something that is at least causes a valid throw from the interpreter. __ bind(no_method); __ pop(rax_want); - if (TaggedStackInterpreter) __ pop(rcx_fail); __ pop(rcx_fail); __ push(rax_want); __ push(rcx_fail); @@ -510,18 +475,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _bound_long_direct_mh: { bool direct_to_method = (ek >= _bound_ref_direct_mh); - BasicType arg_type = T_ILLEGAL; - if (ek == _bound_long_mh || ek == _bound_long_direct_mh) { - arg_type = T_LONG; - } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) { - arg_type = T_INT; - } else { - assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref"); - arg_type = T_OBJECT; - } - int arg_slots = type2size[arg_type]; - int arg_mask = (arg_type == T_OBJECT ? _INSERT_REF_MASK : - arg_slots == 1 ? _INSERT_INT_MASK : _INSERT_LONG_MASK); + BasicType arg_type = T_ILLEGAL; + int arg_mask = _INSERT_NO_MASK; + int arg_slots = -1; + get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots); // make room for the new argument: __ movl(rax_argslot, rcx_bmh_vmargslot); @@ -660,13 +617,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; default: - assert(false, ""); + ShouldNotReachHere(); } - goto finish_int_conversion; - } - finish_int_conversion: - { + // Do the requested conversion and store the value. Register rbx_vminfo = rbx_temp; __ movl(rbx_vminfo, rcx_amh_conversion); assert(CONV_VMINFO_SHIFT == 0, "preshifted"); @@ -692,7 +646,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ shrl(rdx_temp /*, rcx*/); __ bind(done); - __ movl(vmarg, rdx_temp); + __ movl(vmarg, rdx_temp); // Store the value. __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv __ jump_to_method_handle_entry(rcx_recv, rdx_temp); @@ -744,7 +698,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; default: - assert(false, ""); + ShouldNotReachHere(); } __ movptr(rcx_recv, rcx_mh_vmtarget); @@ -778,19 +732,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan if (ek == _adapter_opt_f2d) { __ fld_s(vmarg); // load float to ST0 __ fstp_s(vmarg); // store single - } else if (!TaggedStackInterpreter) { - __ fld_d(vmarg); // load double to ST0 - __ fstp_s(vmarg); // store single } else { - Address vmarg_tag = vmarg.plus_disp(tag_offset); - Address vmarg2 = vmarg.plus_disp(Interpreter::stackElementSize()); - // vmarg2_tag does not participate in this code - Register rbx_tag = rbx_temp; - __ movl(rbx_tag, vmarg_tag); // preserve tag - __ movl(rdx_temp, vmarg2); // get second word of double - __ movl(vmarg_tag, rdx_temp); // align with first word __ fld_d(vmarg); // load double to ST0 - __ movl(vmarg_tag, rbx_tag); // restore tag __ fstp_s(vmarg); // store single } #endif //_LP64 @@ -822,19 +765,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _adapter_opt_rot_2_up: case _adapter_opt_rot_2_down: { - int rotate = 0, swap_slots = 0; - switch ((int)ek) { - case _adapter_opt_swap_1: swap_slots = 1; break; - case _adapter_opt_swap_2: swap_slots = 2; break; - case _adapter_opt_rot_1_up: swap_slots = 1; rotate++; break; - case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break; - case _adapter_opt_rot_2_up: swap_slots = 2; rotate++; break; - case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break; - default: assert(false, ""); - } - - // the real size of the move must be doubled if TaggedStackInterpreter: - int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize ); + int swap_bytes = 0, rotate = 0; + get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate); // 'argslot' is the position of the first argument to swap __ movl(rax_argslot, rcx_amh_vmargslot); @@ -1024,11 +956,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _adapter_opt_spread_more: { // spread an array out into a group of arguments - int length_constant = -1; - switch (ek) { - case _adapter_opt_spread_0: length_constant = 0; break; - case _adapter_opt_spread_1: length_constant = 1; break; - } + int length_constant = get_ek_adapter_opt_spread_info(ek); // find the address of the array argument __ movl(rax_argslot, rcx_amh_vmargslot); @@ -1124,10 +1052,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_source, 0)); __ movptr(Address(rax_argslot, 0), rbx_temp); __ addptr(rsi_source, type2aelembytes(elem_type)); - if (TaggedStackInterpreter) { - __ movptr(Address(rax_argslot, tag_offset), - frame::tag_for_basic_type(elem_type)); - } __ addptr(rax_argslot, Interpreter::stackElementSize()); __ cmpptr(rax_argslot, rdx_argslot_limit); __ jccb(Assembler::less, loop); @@ -1141,10 +1065,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_array, elem_offset)); __ movptr(Address(rax_argslot, slot_offset), rbx_temp); elem_offset += type2aelembytes(elem_type); - if (TaggedStackInterpreter) { - __ movptr(Address(rax_argslot, slot_offset + tag_offset), - frame::tag_for_basic_type(elem_type)); - } slot_offset += Interpreter::stackElementSize(); } } diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 8959b341023..dba7aa3617e 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2915,12 +2915,8 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) __ andl(recv, 0xFF); // recv count is 0 based? Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)); - if (is_invokedynamic) { - __ lea(recv, recv_addr); - } else { - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } + __ movptr(recv, recv_addr); + __ verify_oop(recv); } // do null check if needed diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index fdd492a7495..8c6a9c1e567 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2860,12 +2860,8 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) __ andl(recv, 0xFF); if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); - if (is_invokedynamic) { - __ lea(recv, recv_addr); - } else { - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } + __ movptr(recv, recv_addr); + __ verify_oop(recv); } // do null check if needed diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 1dec4e177b7..4d9b19882f1 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2376,8 +2376,7 @@ void LIRGenerator::do_Invoke(Invoke* x) { CodeEmitInfo* info = state_for(x, x->state()); // invokedynamics can deoptimize. - bool is_invokedynamic = x->code() == Bytecodes::_invokedynamic; - CodeEmitInfo* deopt_info = is_invokedynamic ? state_for(x, x->state_before()) : NULL; + CodeEmitInfo* deopt_info = x->is_invokedynamic() ? state_for(x, x->state_before()) : NULL; invoke_load_arguments(x, args, arg_list); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 1bbf82c41ec..1929c4f00cc 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,6 +137,43 @@ class MethodHandles: AllStatic { _entries[ek] = me; } + // Some adapter helper functions. + static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) { + switch (ek) { + case _bound_int_mh : // fall-thru + case _bound_int_direct_mh : arg_type = T_INT; arg_mask = _INSERT_INT_MASK; break; + case _bound_long_mh : // fall-thru + case _bound_long_direct_mh: arg_type = T_LONG; arg_mask = _INSERT_LONG_MASK; break; + case _bound_ref_mh : // fall-thru + case _bound_ref_direct_mh : arg_type = T_OBJECT; arg_mask = _INSERT_REF_MASK; break; + default: ShouldNotReachHere(); + } + arg_slots = type2size[arg_type]; + } + + static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) { + int swap_slots = 0; + switch (ek) { + case _adapter_opt_swap_1: swap_slots = 1; rotate = 0; break; + case _adapter_opt_swap_2: swap_slots = 2; rotate = 0; break; + case _adapter_opt_rot_1_up: swap_slots = 1; rotate = 1; break; + case _adapter_opt_rot_1_down: swap_slots = 1; rotate = -1; break; + case _adapter_opt_rot_2_up: swap_slots = 2; rotate = 1; break; + case _adapter_opt_rot_2_down: swap_slots = 2; rotate = -1; break; + default: ShouldNotReachHere(); + } + // Return the size of the stack slots to move in bytes. + swap_bytes = swap_slots * Interpreter::stackElementSize(); + } + + static int get_ek_adapter_opt_spread_info(EntryKind ek) { + switch (ek) { + case _adapter_opt_spread_0: return 0; + case _adapter_opt_spread_1: return 1; + default : return -1; + } + } + static methodOop raise_exception_method() { oop rem = JNIHandles::resolve(_raise_exception_method); assert(rem == NULL || rem->is_method(), ""); @@ -392,13 +429,13 @@ class MethodHandles: AllStatic { static void insert_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, int arg_mask, - Register rax_argslot, - Register rbx_temp, Register rdx_temp); + Register argslot_reg, + Register temp_reg, Register temp2_reg); static void remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, - Register rax_argslot, - Register rbx_temp, Register rdx_temp); + Register argslot_reg, + Register temp_reg, Register temp2_reg); }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 11a6320463a..48f4891821a 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2859,6 +2859,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } #endif // _LP64 + // MethodHandles code does not support TaggedStackInterpreter. + if (EnableMethodHandles && TaggedStackInterpreter) { + warning("TaggedStackInterpreter is not supported by MethodHandles code. Disabling TaggedStackInterpreter."); + TaggedStackInterpreter = false; + } + // Check the GC selections again. if (!check_gc_consistency()) { return JNI_EINVAL; From 62d446be0eee5b43304a21d4c7bcaef8717474f3 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Mar 2010 13:52:45 -0700 Subject: [PATCH 29/33] Added tag jdk7-b86 for changeset 41627c4e030e --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 894a468ad2c..ea5265bd6d5 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -60,3 +60,4 @@ e1176f86805fe07fd9fb9da065dc51b47712ce76 jdk7-b82 6880a3af9addb41541e80ebe8cde6f79ec402a58 jdk7-b83 2f3ea057d1ad56cf3b269cdc4de2741411151982 jdk7-b84 cf26288a114be67c39f2758959ce50b60f5ae330 jdk7-b85 +433a60a9c0bf1b26ee7e65cebaa89c541f497aed jdk7-b86 From fde61522159b6ecd0aa487007f4c4790cad32dff Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Mar 2010 13:52:49 -0700 Subject: [PATCH 30/33] Added tag jdk7-b86 for changeset 16a26e16c83f --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 57a200e545a..7b9e2d4d636 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -83,3 +83,4 @@ fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 6c9796468b91dcbb39e09dfa1baf9779ac45eb66 jdk7-b85 418bc80ce13995149eadc9eecbba21d7a9fa02ae hs17-b10 +bf823ef06b4f211e66988d76a2e2669be5c0820e jdk7-b86 From 13244e7bc11705183cda6d44987f1659f552760c Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Mar 2010 13:53:00 -0700 Subject: [PATCH 31/33] Added tag jdk7-b86 for changeset ebd0e0190faf --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 79733ebea92..f745df6a3f9 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -60,3 +60,4 @@ e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77 9027c6b9d7e2c9ca04a1add691b5b50d0f22b1aa jdk7-b83 7cb9388bb1a16365fa5118c5efa38b1cd58be40d jdk7-b84 b396584a3e64988839cca21ea1f7fbdcc9248783 jdk7-b85 +eae6e9ab26064d9ba0e7665dd646a1fd2506fcc1 jdk7-b86 From e549c50c7dc5f18373e170d4ca2ea25422450214 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Thu, 18 Mar 2010 17:21:54 -0700 Subject: [PATCH 32/33] 6936366: Fork HS17 to HS18 - renumber Major and build numbers of JVM Update the Major and build numbers for HS18 fork Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index b6f0792ede5..6faeec67aca 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2009 +HOTSPOT_VM_COPYRIGHT=Copyright 2010 -HS_MAJOR_VER=17 +HS_MAJOR_VER=18 HS_MINOR_VER=0 -HS_BUILD_NUMBER=10 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From 26378d832bd056fc1dea9729d197c829e4595a00 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Tue, 23 Mar 2010 20:28:36 -0700 Subject: [PATCH 33/33] Added tag hs18-b01 for changeset 39a1b68b0062 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 57a200e545a..8ebc08a657e 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -83,3 +83,4 @@ fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 6c9796468b91dcbb39e09dfa1baf9779ac45eb66 jdk7-b85 418bc80ce13995149eadc9eecbba21d7a9fa02ae hs17-b10 +07226e9eab8f74b37346b32715f829a2ef2c3188 hs18-b01