Merge
This commit is contained in:
commit
fd974c3567
1
.hgtags
1
.hgtags
@ -310,3 +310,4 @@ e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62
|
||||
4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65
|
||||
ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
|
||||
56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67
|
||||
5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
|
||||
|
@ -310,3 +310,4 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
|
||||
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
|
||||
dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66
|
||||
f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
|
||||
70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
|
||||
|
@ -310,3 +310,4 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62
|
||||
afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
|
||||
44ee68f7dbacab24a45115fd6a8ccdc7eb6e8f0b jdk9-b66
|
||||
4418697e56f1f43597f55c7cb6573549c6117868 jdk9-b67
|
||||
8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package org.omg.CORBA;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of <tt>Bounds</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org/CORBA/Bounds:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.Bounds that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.Bounds extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.BoundsHelper.id (), "Bounds", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.Bounds read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.Bounds value = new org.omg.CORBA.Bounds ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.Bounds value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package org.omg.CORBA.ORBPackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>ORBPackage/InvalidName</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class InvalidNameHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/ORB/InvalidName:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.ORBPackage.InvalidName that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.ORBPackage.InvalidName extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.ORBPackage.InvalidNameHelper.id (), "InvalidName", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.ORBPackage.InvalidName read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.ORBPackage.InvalidName value = new org.omg.CORBA.ORBPackage.InvalidName ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.ORBPackage.InvalidName value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/BadKind</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BadKindHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/TypeCode/BadKind:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.BadKind that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.BadKind extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BadKindHelper.id (), "BadKind", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.BadKind read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.TypeCodePackage.BadKind value = new org.omg.CORBA.TypeCodePackage.BadKind ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.BadKind value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/Bounds</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/TypeCode/Bounds:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.Bounds that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.Bounds extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BoundsHelper.id (), "Bounds", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.Bounds read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.TypeCodePackage.Bounds value = new org.omg.CORBA.TypeCodePackage.Bounds ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.Bounds value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -470,3 +470,4 @@ bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64
|
||||
e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
|
||||
197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66
|
||||
d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
|
||||
11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
|
||||
|
@ -31,8 +31,8 @@ ifndef OPENJDK
|
||||
REASON = "This JDK does not support SDT probes"
|
||||
else
|
||||
|
||||
# We need a recent GCC for the default
|
||||
ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) )" "0"
|
||||
# We need a recent GCC for the default (4.4 or later)
|
||||
ifeq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) \) \| \( $(CC_VER_MAJOR) \>= 5 \) )" "0"
|
||||
REASON = "gcc version is too old"
|
||||
else
|
||||
|
||||
|
@ -44,6 +44,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
|
||||
$(HOTSPOT_TOPDIR)/test/native_sanity \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
|
||||
#
|
||||
|
||||
BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
|
||||
|
@ -3372,6 +3372,25 @@ operand immI() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 0-bit
|
||||
operand immI0() %{
|
||||
predicate(n->get_int() == 0);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 5-bit
|
||||
operand immI5() %{
|
||||
predicate(Assembler::is_simm5(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 8-bit
|
||||
operand immI8() %{
|
||||
predicate(Assembler::is_simm8(n->get_int()));
|
||||
@ -3381,6 +3400,25 @@ operand immI8() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 10
|
||||
operand immI10() %{
|
||||
predicate(n->get_int() == 10);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 11-bit
|
||||
operand immI11() %{
|
||||
predicate(Assembler::is_simm11(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 13-bit
|
||||
operand immI13() %{
|
||||
predicate(Assembler::is_simm13(n->get_int()));
|
||||
@ -3410,84 +3448,6 @@ operand immI16() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
|
||||
operand immU12() %{
|
||||
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 6-bit
|
||||
operand immU6() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 63);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 11-bit
|
||||
operand immI11() %{
|
||||
predicate(Assembler::is_simm11(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 5-bit
|
||||
operand immI5() %{
|
||||
predicate(Assembler::is_simm5(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Int Immediate non-negative
|
||||
operand immU31()
|
||||
%{
|
||||
predicate(n->get_int() >= 0);
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 0-bit
|
||||
operand immI0() %{
|
||||
predicate(n->get_int() == 0);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 10
|
||||
operand immI10() %{
|
||||
predicate(n->get_int() == 10);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 0-31
|
||||
operand immU5() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 31);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 1-31
|
||||
operand immI_1_31() %{
|
||||
predicate(n->get_int() >= 1 && n->get_int() <= 31);
|
||||
@ -3529,7 +3489,6 @@ operand immI_24() %{
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 255
|
||||
operand immI_255() %{
|
||||
predicate( n->get_int() == 255 );
|
||||
@ -3550,6 +3509,46 @@ operand immI_65535() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 0-31
|
||||
operand immU5() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 31);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 6-bit
|
||||
operand immU6() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 63);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
|
||||
operand immU12() %{
|
||||
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate non-negative
|
||||
operand immU31()
|
||||
%{
|
||||
predicate(n->get_int() >= 0);
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Long Immediate: the value FF
|
||||
operand immL_FF() %{
|
||||
predicate( n->get_long() == 0xFFL );
|
||||
@ -5653,17 +5652,17 @@ instruct loadUB2L(iRegL dst, memory mem) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register
|
||||
instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUB2L_immI(iRegL dst, memory mem, immI mask) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
|
||||
|
||||
size(2*4);
|
||||
format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t"
|
||||
"AND $dst,$mask,$dst" %}
|
||||
format %{ "LDUB $mem,$dst\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"AND $dst,right_n_bits($mask, 8),$dst" %}
|
||||
ins_encode %{
|
||||
__ ldub($mem$$Address, $dst$$Register);
|
||||
__ and3($dst$$Register, $mask$$constant, $dst$$Register);
|
||||
__ and3($dst$$Register, $mask$$constant & right_n_bits(8), $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
@ -5776,20 +5775,20 @@ instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register
|
||||
instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{
|
||||
// Load Unsigned Short/Char (16bit UNsigned) with a 32-bit mask into a Long Register
|
||||
instruct loadUS2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(TEMP dst, TEMP tmp);
|
||||
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
|
||||
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
|
||||
"SET $mask,$tmp\n\t"
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char & 32-bit mask -> long\n\t"
|
||||
"SET right_n_bits($mask, 16),$tmp\n\t"
|
||||
"AND $dst,$tmp,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rtmp = $tmp$$Register;
|
||||
__ lduh($mem$$Address, Rdst);
|
||||
__ set($mask$$constant, Rtmp);
|
||||
__ set($mask$$constant & right_n_bits(16), Rtmp);
|
||||
__ and3(Rdst, Rtmp, Rdst);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
|
@ -5431,18 +5431,18 @@ instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register
|
||||
instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{
|
||||
instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t"
|
||||
format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi\n\t"
|
||||
"AND $dst.lo,$mask" %}
|
||||
"AND $dst.lo,right_n_bits($mask, 8)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzbl(Rdst, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(8));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
@ -5550,19 +5550,19 @@ instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register
|
||||
instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register
|
||||
instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t"
|
||||
format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi\n\t"
|
||||
"AND $dst.lo,$mask" %}
|
||||
"AND $dst.lo,right_n_bits($mask, 16)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzwl(Rdst, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(16));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
@ -4753,17 +4753,17 @@ instruct loadUB2L(rRegL dst, memory mem)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register
|
||||
instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t"
|
||||
"andl $dst, $mask" %}
|
||||
format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"andl $dst, right_n_bits($mask, 8)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzbq(Rdst, $mem$$Address);
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(8));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
@ -4863,17 +4863,17 @@ instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register
|
||||
instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t"
|
||||
"andl $dst, $mask" %}
|
||||
format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
|
||||
"andl $dst, right_n_bits($mask, 16)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzwq(Rdst, $mem$$Address);
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(16));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
@ -1267,10 +1267,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1131,10 +1131,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1478,10 +1478,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1520,10 +1520,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -997,7 +997,16 @@ void os::check_dump_limit(char* buffer, size_t buffsz) {
|
||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
|
||||
status = false;
|
||||
} else {
|
||||
}
|
||||
|
||||
#ifndef ASSERT
|
||||
if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
|
||||
jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
|
||||
status = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status) {
|
||||
const char* cwd = get_current_directory(NULL, 0);
|
||||
int pid = current_process_id();
|
||||
if (cwd != NULL) {
|
||||
@ -1086,10 +1095,6 @@ void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
// Die immediately, no exit hook, no abort hook, no cleanup.
|
||||
void os::die() {
|
||||
win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
|
||||
|
@ -49,25 +49,6 @@ ciMethodHandle* ciCallSite::get_target() const {
|
||||
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::get_context
|
||||
//
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciKlass* ciCallSite::get_context() {
|
||||
assert(!is_constant_call_site(), "");
|
||||
|
||||
VM_ENTRY_MARK;
|
||||
oop call_site_oop = get_oop();
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site_oop);
|
||||
if (ctxk == NULL) {
|
||||
// The call site doesn't have a context associated. Set it to the default context.
|
||||
oop def_context_oop = java_lang_invoke_CallSite::default_context();
|
||||
java_lang_invoke_CallSite::set_context_cas(call_site_oop, def_context_oop, /*expected=*/NULL);
|
||||
ctxk = MethodHandles::get_call_site_context(call_site_oop);
|
||||
}
|
||||
return (CURRENT_ENV->get_metadata(ctxk))->as_klass();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::print
|
||||
//
|
||||
|
@ -43,7 +43,6 @@ public:
|
||||
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciMethodHandle* get_target() const;
|
||||
ciKlass* get_context();
|
||||
|
||||
void print();
|
||||
};
|
||||
|
@ -709,24 +709,23 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor,
|
||||
KlassHandle h_holder(THREAD, holder);
|
||||
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
|
||||
methodHandle dest_method;
|
||||
LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
|
||||
switch (bc) {
|
||||
case Bytecodes::_invokestatic:
|
||||
dest_method =
|
||||
LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
|
||||
LinkResolver::resolve_static_call_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokespecial:
|
||||
dest_method =
|
||||
LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
|
||||
LinkResolver::resolve_special_call_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokeinterface:
|
||||
dest_method =
|
||||
LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
|
||||
h_accessor, true);
|
||||
LinkResolver::linktime_resolve_interface_method_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokevirtual:
|
||||
dest_method =
|
||||
LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
|
||||
h_accessor, true);
|
||||
LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
|
||||
break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
@ -352,11 +352,11 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass,
|
||||
}
|
||||
}
|
||||
|
||||
LinkInfo link_info(_holder->get_instanceKlass(),
|
||||
_name->get_symbol(), _signature->get_symbol(),
|
||||
accessing_klass->get_Klass());
|
||||
fieldDescriptor result;
|
||||
LinkResolver::resolve_field(result, _holder->get_instanceKlass(),
|
||||
_name->get_symbol(), _signature->get_symbol(),
|
||||
accessing_klass->get_Klass(), bc, true, false,
|
||||
KILL_COMPILE_ON_FATAL_(false));
|
||||
LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false));
|
||||
|
||||
// update the hit-cache, unless there is a problem with memory scoping:
|
||||
if (accessing_klass->is_shared() || !is_shared()) {
|
||||
|
@ -453,8 +453,12 @@ int ciInstanceKlass::compute_nonstatic_fields() {
|
||||
|
||||
if (fields == NULL) {
|
||||
// This can happen if this class (java.lang.Class) has invisible fields.
|
||||
_nonstatic_fields = super_fields;
|
||||
return super_fields->length();
|
||||
if (super_fields != NULL) {
|
||||
_nonstatic_fields = super_fields;
|
||||
return super_fields->length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int flen = fields->length();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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
|
||||
@ -786,6 +786,7 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
|
||||
Symbol* h_name = name()->get_symbol();
|
||||
Symbol* h_signature = signature()->get_symbol();
|
||||
|
||||
LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
methodHandle m;
|
||||
// Only do exact lookup if receiver klass has been linked. Otherwise,
|
||||
// the vtable has not been setup, and the LinkResolver will fail.
|
||||
@ -793,9 +794,9 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
|
||||
||
|
||||
InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) {
|
||||
if (holder()->is_interface()) {
|
||||
m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info);
|
||||
} else {
|
||||
m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,7 +840,8 @@ int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) {
|
||||
Symbol* h_name = name()->get_symbol();
|
||||
Symbol* h_signature = signature()->get_symbol();
|
||||
|
||||
vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass);
|
||||
LinkInfo link_info(h_recv, h_name, h_signature, caller_klass);
|
||||
vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info);
|
||||
if (vtable_index == Method::nonvirtual_vtable_index) {
|
||||
// A statically bound method. Return "no such index".
|
||||
vtable_index = Method::invalid_vtable_index;
|
||||
@ -1285,10 +1287,8 @@ bool ciMethod::check_call(int refinfo_index, bool is_static) const {
|
||||
EXCEPTION_MARK;
|
||||
HandleMark hm(THREAD);
|
||||
constantPoolHandle pool (THREAD, get_Method()->constants());
|
||||
methodHandle spec_method;
|
||||
KlassHandle spec_klass;
|
||||
Bytecodes::Code code = (is_static ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual);
|
||||
LinkResolver::resolve_method_statically(spec_method, spec_klass, code, pool, refinfo_index, THREAD);
|
||||
methodHandle spec_method = LinkResolver::resolve_method_statically(code, pool, refinfo_index, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
return false;
|
||||
|
@ -2967,47 +2967,42 @@ int java_lang_invoke_MethodType::rtype_slot_count(oop mt) {
|
||||
|
||||
int java_lang_invoke_CallSite::_target_offset;
|
||||
int java_lang_invoke_CallSite::_context_offset;
|
||||
int java_lang_invoke_CallSite::_default_context_offset;
|
||||
|
||||
void java_lang_invoke_CallSite::compute_offsets() {
|
||||
Klass* k = SystemDictionary::CallSite_klass();
|
||||
if (k != NULL) {
|
||||
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
|
||||
compute_offset(_context_offset, k, vmSymbols::context_name(), vmSymbols::sun_misc_Cleaner_signature());
|
||||
compute_offset(_default_context_offset, k,
|
||||
vmSymbols::DEFAULT_CONTEXT_name(), vmSymbols::sun_misc_Cleaner_signature(),
|
||||
/*is_static=*/true, /*allow_super=*/false);
|
||||
compute_offset(_context_offset, k, vmSymbols::context_name(),
|
||||
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
|
||||
}
|
||||
}
|
||||
|
||||
oop java_lang_invoke_CallSite::context_volatile(oop call_site) {
|
||||
oop java_lang_invoke_CallSite::context(oop call_site) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
|
||||
oop dep_oop = call_site->obj_field_volatile(_context_offset);
|
||||
oop dep_oop = call_site->obj_field(_context_offset);
|
||||
return dep_oop;
|
||||
}
|
||||
|
||||
void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
call_site->obj_field_put_volatile(_context_offset, context);
|
||||
}
|
||||
// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext
|
||||
|
||||
bool java_lang_invoke_CallSite::set_context_cas(oop call_site, oop context, oop expected) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
HeapWord* context_addr = call_site->obj_field_addr<HeapWord>(_context_offset);
|
||||
oop res = oopDesc::atomic_compare_exchange_oop(context, context_addr, expected, true);
|
||||
bool success = (res == expected);
|
||||
if (success) {
|
||||
update_barrier_set((void*)context_addr, context);
|
||||
int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
|
||||
|
||||
void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
|
||||
Klass* k = SystemDictionary::Context_klass();
|
||||
if (k != NULL) {
|
||||
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
oop java_lang_invoke_CallSite::default_context() {
|
||||
InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::CallSite_klass());
|
||||
oop def_context_oop = ik->java_mirror()->obj_field(_default_context_offset);
|
||||
assert(!oopDesc::is_null(def_context_oop), "");
|
||||
return def_context_oop;
|
||||
nmethodBucket* java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
|
||||
assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
|
||||
return (nmethodBucket*) (address) call_site->long_field(_vmdependencies_offset);
|
||||
}
|
||||
|
||||
void java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(oop call_site, nmethodBucket* context) {
|
||||
assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
|
||||
call_site->long_field_put(_vmdependencies_offset, (jlong) (address) context);
|
||||
}
|
||||
|
||||
// Support for java_security_AccessControlContext
|
||||
@ -3403,6 +3398,7 @@ void JavaClasses::compute_offsets() {
|
||||
java_lang_invoke_LambdaForm::compute_offsets();
|
||||
java_lang_invoke_MethodType::compute_offsets();
|
||||
java_lang_invoke_CallSite::compute_offsets();
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets();
|
||||
java_security_AccessControlContext::compute_offsets();
|
||||
// Initialize reflection classes. The layouts of these classes
|
||||
// changed with the new reflection implementation in JDK 1.4, and
|
||||
|
@ -1170,8 +1170,6 @@ class java_lang_invoke_CallSite: AllStatic {
|
||||
private:
|
||||
static int _target_offset;
|
||||
static int _context_offset;
|
||||
static int _default_context_offset;
|
||||
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
@ -1181,11 +1179,7 @@ public:
|
||||
static void set_target( oop site, oop target);
|
||||
static void set_target_volatile( oop site, oop target);
|
||||
|
||||
static oop context_volatile(oop site);
|
||||
static void set_context_volatile(oop site, oop context);
|
||||
static bool set_context_cas (oop site, oop context, oop expected);
|
||||
|
||||
static oop default_context();
|
||||
static oop context(oop site);
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
@ -1197,6 +1191,31 @@ public:
|
||||
static int target_offset_in_bytes() { return _target_offset; }
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects
|
||||
|
||||
#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \
|
||||
macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false)
|
||||
|
||||
class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic {
|
||||
friend class JavaClasses;
|
||||
|
||||
private:
|
||||
static int _vmdependencies_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
static nmethodBucket* vmdependencies(oop context);
|
||||
static void set_vmdependencies(oop context, nmethodBucket* bucket);
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::Context_klass());
|
||||
}
|
||||
static bool is_instance(oop obj);
|
||||
};
|
||||
|
||||
// Interface to java.security.AccessControlContext objects
|
||||
|
||||
class java_security_AccessControlContext: AllStatic {
|
||||
@ -1406,7 +1425,8 @@ class InjectedField {
|
||||
#define ALL_INJECTED_FIELDS(macro) \
|
||||
CLASS_INJECTED_FIELDS(macro) \
|
||||
CLASSLOADER_INJECTED_FIELDS(macro) \
|
||||
MEMBERNAME_INJECTED_FIELDS(macro)
|
||||
MEMBERNAME_INJECTED_FIELDS(macro) \
|
||||
CALLSITECONTEXT_INJECTED_FIELDS(macro)
|
||||
|
||||
// Interface to hard-coded offset checking
|
||||
|
||||
|
@ -49,6 +49,10 @@ inline bool java_lang_invoke_CallSite::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
inline bool java_lang_invoke_MemberName::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ class Ticks;
|
||||
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \
|
||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \
|
||||
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \
|
||||
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \
|
||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \
|
||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \
|
||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/orderAccess.inline.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "services/threadService.hpp"
|
||||
#include "utilities/bytes.hpp"
|
||||
|
||||
#define NOFAILOVER_MAJOR_VERSION 51
|
||||
@ -130,6 +132,16 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
|
||||
return true;
|
||||
}
|
||||
|
||||
// Timer includes any side effects of class verification (resolution,
|
||||
// etc), but not recursive calls to Verifier::verify().
|
||||
JavaThread* jt = (JavaThread*)THREAD;
|
||||
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
|
||||
ClassLoader::perf_class_verify_selftime(),
|
||||
ClassLoader::perf_classes_verified(),
|
||||
jt->get_thread_stat()->perf_recursion_counts_addr(),
|
||||
jt->get_thread_stat()->perf_timers_addr(),
|
||||
PerfClassTraceTime::CLASS_VERIFY);
|
||||
|
||||
// If the class should be verified, first see if we can use the split
|
||||
// verifier. If not, or if verification fails and FailOverToOldVerifier
|
||||
// is set, then call the inference verifier.
|
||||
|
@ -274,12 +274,14 @@
|
||||
/* internal classes known only to the JVM: */ \
|
||||
template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \
|
||||
template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \
|
||||
template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \
|
||||
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
|
||||
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
|
||||
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
|
||||
template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \
|
||||
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
|
||||
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
|
||||
template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \
|
||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||
@ -401,7 +403,7 @@
|
||||
template(protection_domain_name, "protection_domain") \
|
||||
template(signers_name, "signers_name") \
|
||||
template(loader_data_name, "loader_data") \
|
||||
template(dependencies_name, "dependencies") \
|
||||
template(vmdependencies_name, "vmdependencies") \
|
||||
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||
template(getFileURL_name, "getFileURL") \
|
||||
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
|
||||
|
@ -1047,40 +1047,6 @@ void CodeCache::flush_dependents_on(instanceKlassHandle dependee) {
|
||||
}
|
||||
}
|
||||
|
||||
// Flushes compiled methods dependent on a particular CallSite
|
||||
// instance when its target is different than the given MethodHandle.
|
||||
void CodeCache::flush_dependents_on(Handle call_site, Handle method_handle) {
|
||||
assert_lock_strong(Compile_lock);
|
||||
|
||||
if (number_of_nmethods_with_dependencies() == 0) return;
|
||||
|
||||
// CodeCache can only be updated by a thread_in_VM and they will all be
|
||||
// stopped during the safepoint so CodeCache will be safe to update without
|
||||
// holding the CodeCache_lock.
|
||||
|
||||
CallSiteDepChange changes(call_site(), method_handle());
|
||||
|
||||
// Compute the dependent nmethods that have a reference to a
|
||||
// CallSite object. We use InstanceKlass::mark_dependent_nmethod
|
||||
// directly instead of CodeCache::mark_for_deoptimization because we
|
||||
// want dependents on the call site class only not all classes in
|
||||
// the ContextStream.
|
||||
int marked = 0;
|
||||
{
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
|
||||
if (ctxk == NULL) {
|
||||
return; // No dependencies to invalidate yet.
|
||||
}
|
||||
marked = ctxk->mark_dependent_nmethods(changes);
|
||||
}
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HOTSWAP
|
||||
// Flushes compiled methods dependent on dependee in the evolutionary sense
|
||||
void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
|
||||
|
@ -224,7 +224,6 @@ class CodeCache : AllStatic {
|
||||
|
||||
// Flushing and deoptimization
|
||||
static void flush_dependents_on(instanceKlassHandle dependee);
|
||||
static void flush_dependents_on(Handle call_site, Handle method_handle);
|
||||
#ifdef HOTSWAP
|
||||
// Flushing and deoptimization in case of evolution
|
||||
static void flush_evol_dependents_on(instanceKlassHandle dependee);
|
||||
|
@ -117,9 +117,7 @@ void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) {
|
||||
}
|
||||
|
||||
void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
|
||||
ciKlass* ctxk = call_site->get_context();
|
||||
check_ctxk(ctxk);
|
||||
assert_common_3(call_site_target_value, ctxk, call_site, method_handle);
|
||||
assert_common_2(call_site_target_value, call_site, method_handle);
|
||||
}
|
||||
|
||||
// Helper function. If we are adding a new dep. under ctxk2,
|
||||
@ -175,7 +173,6 @@ void Dependencies::assert_common_2(DepType dept,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(dep_implicit_context_arg(dept) == 0, "sanity");
|
||||
if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
|
||||
// look in this bucket for redundant assertions
|
||||
const int stride = 2;
|
||||
@ -389,7 +386,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = {
|
||||
3, // unique_concrete_subtypes_2 ctxk, k1, k2
|
||||
3, // unique_concrete_methods_2 ctxk, m1, m2
|
||||
1, // no_finalizable_subclasses ctxk
|
||||
3 // call_site_target_value ctxk, call_site, method_handle
|
||||
2 // call_site_target_value call_site, method_handle
|
||||
};
|
||||
|
||||
const char* Dependencies::dep_name(Dependencies::DepType dept) {
|
||||
@ -1515,16 +1512,11 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh
|
||||
return find_finalizable_subclass(search_at);
|
||||
}
|
||||
|
||||
Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
|
||||
assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
|
||||
Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
|
||||
assert(!oopDesc::is_null(call_site), "sanity");
|
||||
assert(!oopDesc::is_null(method_handle), "sanity");
|
||||
assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
|
||||
|
||||
Klass* call_site_ctxk = MethodHandles::get_call_site_context(call_site);
|
||||
assert(!Klass::is_null(call_site_ctxk), "call site context should be initialized already");
|
||||
if (recorded_ctxk != call_site_ctxk) {
|
||||
// Stale context
|
||||
return recorded_ctxk;
|
||||
}
|
||||
if (changes == NULL) {
|
||||
// Validate all CallSites
|
||||
if (java_lang_invoke_CallSite::target(call_site) != method_handle)
|
||||
@ -1599,7 +1591,7 @@ Klass* Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* ch
|
||||
Klass* witness = NULL;
|
||||
switch (type()) {
|
||||
case call_site_target_value:
|
||||
witness = check_call_site_target_value(context_type(), argument_oop(1), argument_oop(2), changes);
|
||||
witness = check_call_site_target_value(argument_oop(0), argument_oop(1), changes);
|
||||
break;
|
||||
default:
|
||||
witness = NULL;
|
||||
|
@ -173,7 +173,7 @@ class Dependencies: public ResourceObj {
|
||||
non_klass_types = (1 << call_site_target_value),
|
||||
klass_types = all_types & ~non_klass_types,
|
||||
|
||||
non_ctxk_types = (1 << evol_method),
|
||||
non_ctxk_types = (1 << evol_method) | (1 << call_site_target_value),
|
||||
implicit_ctxk_types = 0,
|
||||
explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types),
|
||||
|
||||
@ -330,7 +330,7 @@ class Dependencies: public ResourceObj {
|
||||
static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2,
|
||||
KlassDepChange* changes = NULL);
|
||||
static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL);
|
||||
static Klass* check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
|
||||
static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
|
||||
// A returned Klass* is NULL if the dependency assertion is still
|
||||
// valid. A non-NULL Klass* is a 'witness' to the assertion
|
||||
// failure, a point in the class hierarchy where the assertion has
|
||||
@ -496,7 +496,7 @@ class Dependencies: public ResourceObj {
|
||||
bool next();
|
||||
|
||||
DepType type() { return _type; }
|
||||
bool is_oop_argument(int i) { return type() == call_site_target_value && i > 0; }
|
||||
bool is_oop_argument(int i) { return type() == call_site_target_value; }
|
||||
uintptr_t get_identifier(int i);
|
||||
|
||||
int argument_count() { return dep_args(type()); }
|
||||
|
@ -565,13 +565,18 @@ nmethod* nmethod::new_nmethod(methodHandle method,
|
||||
// the number of methods compiled. For applications with a lot
|
||||
// classes the slow way is too slow.
|
||||
for (Dependencies::DepStream deps(nm); deps.next(); ) {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
if (deps.type() == Dependencies::call_site_target_value) {
|
||||
// CallSite dependencies are managed on per-CallSite instance basis.
|
||||
oop call_site = deps.argument_oop(0);
|
||||
MethodHandles::add_dependent_nmethod(call_site, nm);
|
||||
} else {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
}
|
||||
// record this nmethod as dependent on this klass
|
||||
InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
|
||||
}
|
||||
|
||||
// record this nmethod as dependent on this klass
|
||||
InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
|
||||
}
|
||||
NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
|
||||
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
|
||||
@ -1464,13 +1469,20 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
|
||||
if (!has_flushed_dependencies()) {
|
||||
set_has_flushed_dependencies();
|
||||
for (Dependencies::DepStream deps(this); deps.next(); ) {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) continue; // ignore things like evol_method
|
||||
|
||||
// During GC the is_alive closure is non-NULL, and is used to
|
||||
// determine liveness of dependees that need to be updated.
|
||||
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
|
||||
InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
|
||||
if (deps.type() == Dependencies::call_site_target_value) {
|
||||
// CallSite dependencies are managed on per-CallSite instance basis.
|
||||
oop call_site = deps.argument_oop(0);
|
||||
MethodHandles::remove_dependent_nmethod(call_site, this);
|
||||
} else {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
}
|
||||
// During GC the is_alive closure is non-NULL, and is used to
|
||||
// determine liveness of dependees that need to be updated.
|
||||
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
|
||||
InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,9 +254,9 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
|
||||
if (_gc_cause != GCCause::_gc_locker &&
|
||||
gch->total_full_collections_completed() <= _full_gc_count_before) {
|
||||
// maybe we should change the condition to test _gc_cause ==
|
||||
// GCCause::_java_lang_system_gc, instead of
|
||||
// _gc_cause != GCCause::_gc_locker
|
||||
assert(_gc_cause == GCCause::_java_lang_system_gc,
|
||||
// GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run,
|
||||
// instead of _gc_cause != GCCause::_gc_locker
|
||||
assert(GCCause::is_user_requested_gc(_gc_cause),
|
||||
"the only way to get here if this was a System.gc()-induced GC");
|
||||
assert(ExplicitGCInvokesConcurrent, "Error");
|
||||
// Now, wait for witnessing concurrent gc cycle to complete,
|
||||
|
@ -43,7 +43,7 @@ GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) {
|
||||
}
|
||||
|
||||
// Run a task; returns when the task is done, or the workers yield,
|
||||
// or the task is aborted, or the work gang is terminated via stop().
|
||||
// or the task is aborted.
|
||||
// A task that has been yielded can be continued via this interface
|
||||
// by using the same task repeatedly as the argument to the call.
|
||||
// It is expected that the YieldingFlexibleGangTask carries the appropriate
|
||||
@ -297,16 +297,9 @@ void YieldingFlexibleGangWorker::loop() {
|
||||
WorkData data;
|
||||
int id;
|
||||
while (true) {
|
||||
// Check if there is work to do or if we have been asked
|
||||
// to terminate
|
||||
// Check if there is work to do.
|
||||
gang()->internal_worker_poll(&data);
|
||||
if (data.terminate()) {
|
||||
// We have been asked to terminate.
|
||||
assert(gang()->task() == NULL, "No task binding");
|
||||
// set_status(TERMINATED);
|
||||
return;
|
||||
} else if (data.task() != NULL &&
|
||||
data.sequence_number() != previous_sequence_number) {
|
||||
if (data.task() != NULL && data.sequence_number() != previous_sequence_number) {
|
||||
// There is work to be done.
|
||||
// First check if we need to become active or if there
|
||||
// are already the requisite number of workers
|
||||
|
@ -176,7 +176,7 @@ public:
|
||||
GangWorker* allocate_worker(uint which);
|
||||
|
||||
// Run a task; returns when the task is done, or the workers yield,
|
||||
// or the task is aborted, or the work gang is terminated via stop().
|
||||
// or the task is aborted.
|
||||
// A task that has been yielded can be continued via this same interface
|
||||
// by using the same task repeatedly as the argument to the call.
|
||||
// It is expected that the YieldingFlexibleGangTask carries the appropriate
|
||||
|
@ -1183,7 +1183,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||
IsGCActiveMark x;
|
||||
|
||||
// Timing
|
||||
assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
|
||||
assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
|
||||
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
|
||||
|
||||
{
|
||||
@ -2199,6 +2199,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
switch (cause) {
|
||||
case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
|
||||
case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent;
|
||||
case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
|
||||
case GCCause::_g1_humongous_allocation: return true;
|
||||
case GCCause::_update_allocation_context_stats_inc: return true;
|
||||
case GCCause::_wb_conc_mark: return true;
|
||||
|
@ -324,7 +324,8 @@ private:
|
||||
// explicitly started if:
|
||||
// (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
|
||||
// (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
|
||||
// (c) cause == _g1_humongous_allocation
|
||||
// (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent.
|
||||
// (d) cause == _g1_humongous_allocation
|
||||
bool should_do_concurrent_full_gc(GCCause::Cause cause);
|
||||
|
||||
// Keeps track of how many "old marking cycles" (i.e., Full GCs or
|
||||
|
@ -168,7 +168,7 @@ void VM_G1IncCollectionPause::doit_epilogue() {
|
||||
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
|
||||
// that just started (or maybe one that was already in progress) to
|
||||
// finish.
|
||||
if (_gc_cause == GCCause::_java_lang_system_gc &&
|
||||
if (GCCause::is_user_requested_gc(_gc_cause) &&
|
||||
_should_initiate_conc_mark) {
|
||||
assert(ExplicitGCInvokesConcurrent,
|
||||
"the only way to be here is if ExplicitGCInvokesConcurrent is set");
|
||||
|
@ -130,7 +130,7 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
|
||||
// Update the pause time.
|
||||
_major_timer.stop();
|
||||
|
||||
if (gc_cause != GCCause::_java_lang_system_gc ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
double major_pause_in_seconds = _major_timer.seconds();
|
||||
double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;
|
||||
|
@ -272,7 +272,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
||||
// Don't check if the size_policy is ready here. Let
|
||||
// the size_policy check that internally.
|
||||
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
|
||||
((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
(!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC)) {
|
||||
// Swap the survivor spaces if from_space is empty. The
|
||||
// resize_young_gen() called below is normally used after
|
||||
|
@ -2053,7 +2053,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer);
|
||||
|
||||
bool max_on_system_gc = UseMaximumCompactionOnSystemGC
|
||||
&& gc_cause == GCCause::_java_lang_system_gc;
|
||||
&& GCCause::is_user_requested_gc(gc_cause);
|
||||
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
|
||||
|
||||
COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
|
||||
@ -2089,7 +2089,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
// Don't check if the size_policy is ready here. Let
|
||||
// the size_policy check that internally.
|
||||
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
|
||||
((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
(!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC)) {
|
||||
// Swap the survivor spaces if from_space is empty. The
|
||||
// resize_young_gen() called below is normally used after
|
||||
|
@ -290,7 +290,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
|
||||
AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
|
||||
|
||||
if ((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
// Gather the feedback data for eden occupancy.
|
||||
young_gen->eden_space()->accumulate_statistics();
|
||||
|
@ -960,7 +960,7 @@ void DefNewGeneration::gc_epilogue(bool full) {
|
||||
GCCause::to_string(gch->gc_cause()));
|
||||
}
|
||||
assert(gch->gc_cause() == GCCause::_scavenge_alot ||
|
||||
(gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
|
||||
(GCCause::is_user_requested_gc(gch->gc_cause()) && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
|
||||
!gch->incremental_collection_failed(),
|
||||
"Twice in a row");
|
||||
seen_incremental_collection_failed = false;
|
||||
|
@ -244,7 +244,7 @@ void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) {
|
||||
// Update the pause time.
|
||||
_minor_timer.stop();
|
||||
|
||||
if (gc_cause != GCCause::_java_lang_system_gc ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
double minor_pause_in_seconds = _minor_timer.seconds();
|
||||
double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS;
|
||||
|
@ -103,6 +103,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
|
||||
case _last_ditch_collection:
|
||||
return "Last ditch collection";
|
||||
|
||||
case _dcmd_gc_run:
|
||||
return "Diagnostic Command";
|
||||
|
||||
case _last_gc_cause:
|
||||
return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
|
||||
|
||||
|
@ -74,12 +74,15 @@ class GCCause : public AllStatic {
|
||||
_g1_humongous_allocation,
|
||||
|
||||
_last_ditch_collection,
|
||||
|
||||
_dcmd_gc_run,
|
||||
|
||||
_last_gc_cause
|
||||
};
|
||||
|
||||
inline static bool is_user_requested_gc(GCCause::Cause cause) {
|
||||
return (cause == GCCause::_java_lang_system_gc ||
|
||||
cause == GCCause::_jvmti_force_gc);
|
||||
cause == GCCause::_dcmd_gc_run);
|
||||
}
|
||||
|
||||
inline static bool is_serviceability_requested_gc(GCCause::Cause
|
||||
|
@ -304,9 +304,16 @@ bool GenCollectedHeap::must_clear_all_soft_refs() {
|
||||
}
|
||||
|
||||
bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
return UseConcMarkSweepGC &&
|
||||
((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||
(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
|
||||
if (!UseConcMarkSweepGC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (cause) {
|
||||
case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
|
||||
case GCCause::_java_lang_system_gc:
|
||||
case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,
|
||||
|
@ -47,7 +47,6 @@ AbstractWorkGang::AbstractWorkGang(const char* name,
|
||||
/* allow_vm_block */ are_GC_task_threads,
|
||||
Monitor::_safepoint_check_sometimes);
|
||||
assert(monitor() != NULL, "Failed to allocate monitor");
|
||||
_terminate = false;
|
||||
_task = NULL;
|
||||
_sequence_number = 0;
|
||||
_started_workers = 0;
|
||||
@ -106,18 +105,6 @@ bool WorkGang::initialize_workers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractWorkGang::~AbstractWorkGang() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Destructing work gang %s", name());
|
||||
}
|
||||
stop(); // stop all the workers
|
||||
for (uint worker = 0; worker < total_workers(); worker += 1) {
|
||||
delete gang_worker(worker);
|
||||
}
|
||||
delete gang_workers();
|
||||
delete monitor();
|
||||
}
|
||||
|
||||
GangWorker* AbstractWorkGang::gang_worker(uint i) const {
|
||||
// Array index bounds checking.
|
||||
GangWorker* result = NULL;
|
||||
@ -175,28 +162,9 @@ void FlexibleWorkGang::run_task(AbstractGangTask* task) {
|
||||
WorkGang::run_task(task, (uint) active_workers());
|
||||
}
|
||||
|
||||
void AbstractWorkGang::stop() {
|
||||
// Tell all workers to terminate, then wait for them to become inactive.
|
||||
MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
|
||||
}
|
||||
_task = NULL;
|
||||
_terminate = true;
|
||||
monitor()->notify_all();
|
||||
while (finished_workers() < active_workers()) {
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Waiting in work gang %s: %u/%u finished",
|
||||
name(), finished_workers(), active_workers());
|
||||
}
|
||||
monitor()->wait(/* no_safepoint_check */ true);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
|
||||
assert(monitor()->owned_by_self(), "worker_poll is an internal method");
|
||||
assert(data != NULL, "worker data is null");
|
||||
data->set_terminate(terminate());
|
||||
data->set_task(task());
|
||||
data->set_sequence_number(sequence_number());
|
||||
}
|
||||
@ -259,7 +227,7 @@ void GangWorker::initialize() {
|
||||
void GangWorker::loop() {
|
||||
int previous_sequence_number = 0;
|
||||
Monitor* gang_monitor = gang()->monitor();
|
||||
for ( ; /* !terminate() */; ) {
|
||||
for ( ; ; ) {
|
||||
WorkData data;
|
||||
int part; // Initialized below.
|
||||
{
|
||||
@ -272,8 +240,6 @@ void GangWorker::loop() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print("Polled outside for work in gang %s worker %u",
|
||||
gang()->name(), id());
|
||||
tty->print(" terminate: %s",
|
||||
data.terminate() ? "true" : "false");
|
||||
tty->print(" sequence: %d (prev: %d)",
|
||||
data.sequence_number(), previous_sequence_number);
|
||||
if (data.task() != NULL) {
|
||||
@ -283,13 +249,7 @@ void GangWorker::loop() {
|
||||
}
|
||||
tty->cr();
|
||||
}
|
||||
for ( ; /* break or return */; ) {
|
||||
// Terminate if requested.
|
||||
if (data.terminate()) {
|
||||
gang()->internal_note_finish();
|
||||
gang_monitor->notify_all();
|
||||
return;
|
||||
}
|
||||
for ( ; /* break */; ) {
|
||||
// Check for new work.
|
||||
if ((data.task() != NULL) &&
|
||||
(data.sequence_number() != previous_sequence_number)) {
|
||||
@ -306,8 +266,6 @@ void GangWorker::loop() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print("Polled inside for work in gang %s worker %u",
|
||||
gang()->name(), id());
|
||||
tty->print(" terminate: %s",
|
||||
data.terminate() ? "true" : "false");
|
||||
tty->print(" sequence: %d (prev: %d)",
|
||||
data.sequence_number(), previous_sequence_number);
|
||||
if (data.task() != NULL) {
|
||||
|
@ -103,16 +103,15 @@ class AbstractGangTaskWOopQueues : public AbstractGangTask {
|
||||
// An abstract class representing a gang of workers.
|
||||
// You subclass this to supply an implementation of run_task().
|
||||
class AbstractWorkGang: public CHeapObj<mtInternal> {
|
||||
// Here's the public interface to this class.
|
||||
protected:
|
||||
// Work gangs are never deleted, so no need to cleanup.
|
||||
~AbstractWorkGang() { ShouldNotReachHere(); }
|
||||
public:
|
||||
// Constructor and destructor.
|
||||
// Constructor.
|
||||
AbstractWorkGang(const char* name, bool are_GC_task_threads,
|
||||
bool are_ConcurrentGC_threads);
|
||||
~AbstractWorkGang();
|
||||
// Run a task, returns when the task is done (or terminated).
|
||||
virtual void run_task(AbstractGangTask* task) = 0;
|
||||
// Stop and terminate all workers.
|
||||
virtual void stop();
|
||||
// Return true if more workers should be applied to the task.
|
||||
virtual bool needs_more_workers() const { return true; }
|
||||
public:
|
||||
@ -129,8 +128,6 @@ protected:
|
||||
Monitor* _monitor;
|
||||
// The count of the number of workers in the gang.
|
||||
uint _total_workers;
|
||||
// Whether the workers should terminate.
|
||||
bool _terminate;
|
||||
// The array of worker threads for this gang.
|
||||
// This is only needed for cleaning up.
|
||||
GangWorker** _gang_workers;
|
||||
@ -153,9 +150,6 @@ public:
|
||||
virtual uint active_workers() const {
|
||||
return _total_workers;
|
||||
}
|
||||
bool terminate() const {
|
||||
return _terminate;
|
||||
}
|
||||
GangWorker** gang_workers() const {
|
||||
return _gang_workers;
|
||||
}
|
||||
@ -205,21 +199,16 @@ protected:
|
||||
class WorkData: public StackObj {
|
||||
// This would be a struct, but I want accessor methods.
|
||||
private:
|
||||
bool _terminate;
|
||||
AbstractGangTask* _task;
|
||||
int _sequence_number;
|
||||
public:
|
||||
// Constructor and destructor
|
||||
WorkData() {
|
||||
_terminate = false;
|
||||
_task = NULL;
|
||||
_sequence_number = 0;
|
||||
}
|
||||
~WorkData() {
|
||||
}
|
||||
// Accessors and modifiers
|
||||
bool terminate() const { return _terminate; }
|
||||
void set_terminate(bool value) { _terminate = value; }
|
||||
AbstractGangTask* task() const { return _task; }
|
||||
void set_task(AbstractGangTask* value) { _task = value; }
|
||||
int sequence_number() const { return _sequence_number; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
|
||||
@ -147,13 +147,10 @@ BasicType Bytecode_member_ref::result_type() const {
|
||||
|
||||
|
||||
methodHandle Bytecode_invoke::static_target(TRAPS) {
|
||||
methodHandle m;
|
||||
KlassHandle resolved_klass;
|
||||
constantPoolHandle constants(THREAD, this->constants());
|
||||
|
||||
Bytecodes::Code bc = invoke_code();
|
||||
LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle()));
|
||||
return m;
|
||||
return LinkResolver::resolve_method_statically(bc, constants, index(), THREAD);
|
||||
}
|
||||
|
||||
Handle Bytecode_invoke::appendix(TRAPS) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
|
||||
@ -36,7 +36,7 @@
|
||||
// that method. If the info is invalid, the link has not been resolved
|
||||
// successfully.
|
||||
|
||||
class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
class CallInfo : public StackObj {
|
||||
public:
|
||||
// Ways that a method call might be selected (or not) based on receiver type.
|
||||
// Note that an invokevirtual instruction might be linked with no_dispatch,
|
||||
@ -58,11 +58,22 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix)
|
||||
Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites)
|
||||
|
||||
void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
|
||||
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS);
|
||||
void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS);
|
||||
void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
|
||||
void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS);
|
||||
void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS);
|
||||
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
int itable_index, TRAPS);
|
||||
void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
int vtable_index, TRAPS);
|
||||
void set_handle(const methodHandle& resolved_method,
|
||||
Handle resolved_appendix, Handle resolved_method_type, TRAPS);
|
||||
void set_common(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
CallKind kind,
|
||||
int index, TRAPS);
|
||||
|
||||
friend class LinkResolver;
|
||||
|
||||
@ -113,6 +124,37 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
void print() PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
|
||||
// Condensed information from constant pool to use to resolve the method or field.
|
||||
// resolved_klass = specified class (i.e., static receiver class)
|
||||
// current_klass = sending method holder (i.e., class containing the method
|
||||
// containing the call being resolved)
|
||||
class LinkInfo : public StackObj {
|
||||
Symbol* _name; // extracted from JVM_CONSTANT_NameAndType
|
||||
Symbol* _signature;
|
||||
KlassHandle _resolved_klass; // class that the constant pool entry points to
|
||||
KlassHandle _current_klass; // class that owns the constant pool
|
||||
bool _check_access;
|
||||
public:
|
||||
LinkInfo(constantPoolHandle pool, int index, TRAPS);
|
||||
// Condensed information from other call sites within the vm.
|
||||
LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
|
||||
KlassHandle current_klass, bool check_access = true) :
|
||||
_resolved_klass(resolved_klass),
|
||||
_name(name), _signature(signature), _current_klass(current_klass),
|
||||
_check_access(check_access) {}
|
||||
|
||||
// accessors
|
||||
Symbol* name() const { return _name; }
|
||||
Symbol* signature() const { return _signature; }
|
||||
KlassHandle resolved_klass() const { return _resolved_klass; }
|
||||
KlassHandle current_klass() const { return _current_klass; }
|
||||
bool check_access() const { return _check_access; }
|
||||
char* method_string() const;
|
||||
|
||||
void print() PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
// Link information for getfield/putfield & getstatic/putstatic bytecodes
|
||||
// is represented using a fieldDescriptor.
|
||||
|
||||
@ -124,85 +166,136 @@ class LinkResolver: AllStatic {
|
||||
friend class klassItable;
|
||||
|
||||
private:
|
||||
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS);
|
||||
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
|
||||
KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
|
||||
|
||||
static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static methodHandle lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve, TRAPS);
|
||||
static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
|
||||
Handle *appendix_result_or_null,
|
||||
Handle *method_type_result, TRAPS);
|
||||
// Not Linktime so doesn't take LinkInfo
|
||||
static methodHandle lookup_instance_method_in_klasses (
|
||||
KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
|
||||
static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
|
||||
// Similar loader constraint checking functions that throw
|
||||
// LinkageError with descriptive message.
|
||||
static void check_method_loader_constraints(const LinkInfo& link_info,
|
||||
const methodHandle& resolved_method,
|
||||
const char* method_type, TRAPS);
|
||||
static void check_field_loader_constraints(Symbol* field, Symbol* sig,
|
||||
KlassHandle current_klass,
|
||||
KlassHandle sel_klass, TRAPS);
|
||||
|
||||
static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, TRAPS);
|
||||
static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS);
|
||||
static methodHandle resolve_interface_method(const LinkInfo& link_info, bool nostatics, TRAPS);
|
||||
static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS);
|
||||
|
||||
static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_virtual_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS);
|
||||
|
||||
static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_special_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle current_klass,
|
||||
bool check_access, TRAPS);
|
||||
static void runtime_resolve_virtual_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
Handle recv,
|
||||
KlassHandle recv_klass,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_interface_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
Handle recv,
|
||||
KlassHandle recv_klass,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
|
||||
static void check_field_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, fieldDescriptor& fd, TRAPS);
|
||||
static void check_method_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, methodHandle sel_method, TRAPS);
|
||||
static void check_field_accessability(KlassHandle ref_klass,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle sel_klass,
|
||||
const fieldDescriptor& fd, TRAPS);
|
||||
static void check_method_accessability(KlassHandle ref_klass,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle sel_klass,
|
||||
const methodHandle& sel_method, TRAPS);
|
||||
|
||||
// runtime resolving from constant pool
|
||||
static void resolve_invokestatic (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokespecial (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokevirtual (CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokeinterface(CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokedynamic (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokehandle (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
public:
|
||||
// constant pool resolving
|
||||
static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS);
|
||||
|
||||
// static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target
|
||||
static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result,
|
||||
Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS);
|
||||
// static resolving calls (will not run any Java code);
|
||||
// used only from Bytecode_invoke::static_target
|
||||
static methodHandle resolve_method_statically(Bytecodes::Code code,
|
||||
constantPoolHandle pool,
|
||||
int index, TRAPS);
|
||||
|
||||
// runtime/static resolving for fields
|
||||
static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature,
|
||||
KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS);
|
||||
static void resolve_field_access(fieldDescriptor& result,
|
||||
constantPoolHandle pool,
|
||||
int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
|
||||
Bytecodes::Code access_kind,
|
||||
bool initialize_class, TRAPS);
|
||||
|
||||
// source of access_kind codes:
|
||||
static Bytecodes::Code field_access_kind(bool is_static, bool is_put) {
|
||||
return (is_static
|
||||
? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic)
|
||||
: (is_put ? Bytecodes::_putfield : Bytecodes::_getfield ));
|
||||
}
|
||||
static void resolve_static_call (CallInfo& result,
|
||||
const LinkInfo& link_info,
|
||||
bool initialize_klass, TRAPS);
|
||||
static void resolve_special_call (CallInfo& result,
|
||||
const LinkInfo& link_info,
|
||||
TRAPS);
|
||||
static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass,
|
||||
const LinkInfo& link_info,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
|
||||
const LinkInfo& link_info,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_handle_call (CallInfo& result,
|
||||
const LinkInfo& link_info, TRAPS);
|
||||
static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier,
|
||||
Symbol* method_name, Symbol* method_signature,
|
||||
KlassHandle current_klass, TRAPS);
|
||||
|
||||
// runtime resolving:
|
||||
// resolved_klass = specified class (i.e., static receiver class)
|
||||
// current_klass = sending method holder (i.e., class containing the method containing the call being resolved)
|
||||
static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
|
||||
static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
|
||||
static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
|
||||
// same as above for compile-time resolution; but returns null handle instead of throwing
|
||||
// an exception on error also, does not initialize klass (i.e., no side effects)
|
||||
static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
static methodHandle resolve_static_call_or_null (const LinkInfo& link_info);
|
||||
static methodHandle resolve_special_call_or_null (const LinkInfo& link_info);
|
||||
|
||||
// same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
|
||||
// also, does not initialize klass (i.e., no side effects)
|
||||
static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method);
|
||||
static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method);
|
||||
|
||||
// same as above for compile-time resolution; returns vtable_index if current_klass if linked
|
||||
static int resolve_virtual_vtable_index (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
|
||||
static int resolve_virtual_vtable_index (KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
|
||||
// static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful)
|
||||
static methodHandle linktime_resolve_virtual_method_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
|
||||
static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
|
||||
static methodHandle linktime_resolve_virtual_method_or_null (const LinkInfo& link_info);
|
||||
static methodHandle linktime_resolve_interface_method_or_null(const LinkInfo& link_info);
|
||||
|
||||
// runtime resolving from constant pool
|
||||
static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokehandle (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
|
||||
static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_invoke(CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index,
|
||||
Bytecodes::Code byte, TRAPS);
|
||||
private:
|
||||
static void trace_method_resolution(const char* prefix, KlassHandle klass,
|
||||
KlassHandle resolved_klass,
|
||||
const methodHandle& method) PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP
|
||||
|
@ -614,8 +614,7 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||
Metachunk* _chunks_in_use[NumberOfInUseLists];
|
||||
Metachunk* _current_chunk;
|
||||
|
||||
// Number of small chunks to allocate to a manager
|
||||
// If class space manager, small chunks are unlimited
|
||||
// Maximum number of small chunks to allocate to a SpaceManager
|
||||
static uint const _small_chunk_limit;
|
||||
|
||||
// Sum of all space in allocated chunks
|
||||
@ -730,6 +729,8 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||
// Block allocation and deallocation.
|
||||
// Allocates a block from the current chunk
|
||||
MetaWord* allocate(size_t word_size);
|
||||
// Allocates a block from a small chunk
|
||||
MetaWord* get_small_chunk_and_allocate(size_t word_size);
|
||||
|
||||
// Helper for allocations
|
||||
MetaWord* allocate_work(size_t word_size);
|
||||
@ -2011,9 +2012,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
|
||||
size_t SpaceManager::calc_chunk_size(size_t word_size) {
|
||||
|
||||
// Decide between a small chunk and a medium chunk. Up to
|
||||
// _small_chunk_limit small chunks can be allocated but
|
||||
// once a medium chunk has been allocated, no more small
|
||||
// chunks will be allocated.
|
||||
// _small_chunk_limit small chunks can be allocated.
|
||||
// After that a medium chunk is preferred.
|
||||
size_t chunk_word_size;
|
||||
if (chunks_in_use(MediumIndex) == NULL &&
|
||||
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
|
||||
@ -2081,7 +2081,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
|
||||
word_size, words_used, words_left);
|
||||
}
|
||||
|
||||
// Get another chunk out of the virtual space
|
||||
// Get another chunk
|
||||
size_t grow_chunks_by_words = calc_chunk_size(word_size);
|
||||
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
|
||||
|
||||
@ -2412,6 +2412,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
||||
return next;
|
||||
}
|
||||
|
||||
/*
|
||||
* The policy is to allocate up to _small_chunk_limit small chunks
|
||||
* after which only medium chunks are allocated. This is done to
|
||||
* reduce fragmentation. In some cases, this can result in a lot
|
||||
* of small chunks being allocated to the point where it's not
|
||||
* possible to expand. If this happens, there may be no medium chunks
|
||||
* available and OOME would be thrown. Instead of doing that,
|
||||
* if the allocation request size fits in a small chunk, an attempt
|
||||
* will be made to allocate a small chunk.
|
||||
*/
|
||||
MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
|
||||
if (word_size + Metachunk::overhead() > small_chunk_size()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
|
||||
MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
|
||||
|
||||
Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
|
||||
|
||||
MetaWord* mem = NULL;
|
||||
|
||||
if (chunk != NULL) {
|
||||
// Add chunk to the in-use chunk list and do an allocation from it.
|
||||
// Add to this manager's list of chunks in use.
|
||||
add_chunk(chunk, false);
|
||||
mem = chunk->allocate(word_size);
|
||||
|
||||
inc_used_metrics(word_size);
|
||||
|
||||
// Track metaspace memory usage statistic.
|
||||
track_metaspace_memory_usage();
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
MetaWord* SpaceManager::allocate(size_t word_size) {
|
||||
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
|
||||
|
||||
@ -3560,7 +3597,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
|
||||
SpaceManager* sm;
|
||||
if (is_class_space_allocation(mdtype)) {
|
||||
sm = loader_data->metaspace_non_null()->class_vsm();
|
||||
} else {
|
||||
sm = loader_data->metaspace_non_null()->vsm();
|
||||
}
|
||||
|
||||
result = sm->get_small_chunk_and_allocate(word_size);
|
||||
|
||||
if (result == NULL) {
|
||||
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero initialize.
|
||||
|
@ -622,14 +622,6 @@ bool InstanceKlass::link_class_impl(
|
||||
if (!this_k->is_linked()) {
|
||||
if (!this_k->is_rewritten()) {
|
||||
{
|
||||
// Timer includes any side effects of class verification (resolution,
|
||||
// etc), but not recursive entry into verify_code().
|
||||
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
|
||||
ClassLoader::perf_class_verify_selftime(),
|
||||
ClassLoader::perf_classes_verified(),
|
||||
jt->get_thread_stat()->perf_recursion_counts_addr(),
|
||||
jt->get_thread_stat()->perf_timers_addr(),
|
||||
PerfClassTraceTime::CLASS_VERIFY);
|
||||
bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
@ -1830,11 +1822,10 @@ int nmethodBucket::decrement() {
|
||||
// are dependent on the changes that were passed in and mark them for
|
||||
// deoptimization. Returns the number of nmethods found.
|
||||
//
|
||||
int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
int found = 0;
|
||||
nmethodBucket* b = _dependencies;
|
||||
while (b != NULL) {
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
// since dependencies aren't removed until an nmethod becomes a zombie,
|
||||
// the dependency list may contain nmethods which aren't alive.
|
||||
@ -1842,7 +1833,6 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
if (TraceDependencies) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Marked for deoptimization");
|
||||
tty->print_cr(" context = %s", this->external_name());
|
||||
changes.print();
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
@ -1850,36 +1840,119 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
nm->mark_for_deoptimization();
|
||||
found++;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//
|
||||
// Add an nmethodBucket to the list of dependencies for this nmethod.
|
||||
// It's possible that an nmethod has multiple dependencies on this klass
|
||||
// so a count is kept for each bucket to guarantee that creation and
|
||||
// deletion of dependencies is consistent. Returns new head of the list.
|
||||
//
|
||||
nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
b->increment();
|
||||
return deps;
|
||||
}
|
||||
}
|
||||
return new nmethodBucket(nm, deps);
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement count of the nmethod in the dependency list and remove
|
||||
// the bucket completely when the count goes to 0. This method must
|
||||
// find a corresponding bucket otherwise there's a bug in the
|
||||
// recording of dependencies. Returns true if the bucket is ready for reclamation.
|
||||
//
|
||||
bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
int val = b->decrement();
|
||||
guarantee(val >= 0, err_msg("Underflow: %d", val));
|
||||
return (val == 0);
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
tty->print_raw_cr("### can't find dependent nmethod");
|
||||
nm->print();
|
||||
#endif // ASSERT
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Reclaim all unused buckets. Returns new head of the list.
|
||||
//
|
||||
nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
|
||||
nmethodBucket* first = deps;
|
||||
nmethodBucket* last = NULL;
|
||||
nmethodBucket* b = first;
|
||||
|
||||
while (b != NULL) {
|
||||
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
|
||||
nmethodBucket* next = b->next();
|
||||
if (b->count() == 0) {
|
||||
if (last == NULL) {
|
||||
first = next;
|
||||
} else {
|
||||
last->set_next(next);
|
||||
}
|
||||
delete b;
|
||||
// last stays the same.
|
||||
} else {
|
||||
last = b;
|
||||
}
|
||||
b = next;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) {
|
||||
int idx = 0;
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
tty->print("[%d] count=%d { ", idx++, b->count());
|
||||
if (!verbose) {
|
||||
nm->print_on(tty, "nmethod");
|
||||
tty->print_cr(" } ");
|
||||
} else {
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
tty->print_cr("--- } ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
#ifdef ASSERT
|
||||
int count = b->count();
|
||||
assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
return nmethodBucket::mark_dependent_nmethods(_dependencies, changes);
|
||||
}
|
||||
|
||||
void InstanceKlass::clean_dependent_nmethods() {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
if (has_unloaded_dependent()) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
|
||||
|
||||
nmethodBucket* next = b->next();
|
||||
|
||||
if (b->count() == 0) {
|
||||
if (last == NULL) {
|
||||
_dependencies = next;
|
||||
} else {
|
||||
last->set_next(next);
|
||||
}
|
||||
delete b;
|
||||
// last stays the same.
|
||||
} else {
|
||||
last = b;
|
||||
}
|
||||
|
||||
b = next;
|
||||
}
|
||||
_dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
|
||||
set_has_unloaded_dependent(false);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
@ -1893,90 +1966,26 @@ void InstanceKlass::clean_dependent_nmethods() {
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Add an nmethodBucket to the list of dependencies for this nmethod.
|
||||
// It's possible that an nmethod has multiple dependencies on this klass
|
||||
// so a count is kept for each bucket to guarantee that creation and
|
||||
// deletion of dependencies is consistent.
|
||||
//
|
||||
void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
b->increment();
|
||||
return;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
_dependencies = new nmethodBucket(nm, _dependencies);
|
||||
_dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Decrement count of the nmethod in the dependency list and remove
|
||||
// the bucket competely when the count goes to 0. This method must
|
||||
// find a corresponding bucket otherwise there's a bug in the
|
||||
// recording of dependecies.
|
||||
//
|
||||
void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
int val = b->decrement();
|
||||
guarantee(val >= 0, err_msg("Underflow: %d", val));
|
||||
if (val == 0) {
|
||||
set_has_unloaded_dependent(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
last = b;
|
||||
b = b->next();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
|
||||
nm->print();
|
||||
#endif // ASSERT
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
|
||||
set_has_unloaded_dependent(true);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void InstanceKlass::print_dependent_nmethods(bool verbose) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
int idx = 0;
|
||||
while (b != NULL) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
tty->print("[%d] count=%d { ", idx++, b->count());
|
||||
if (!verbose) {
|
||||
nm->print_on(tty, "nmethod");
|
||||
tty->print_cr(" } ");
|
||||
} else {
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
tty->print_cr("--- } ");
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
|
||||
}
|
||||
|
||||
|
||||
bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
#ifdef ASSERT
|
||||
int count = b->count();
|
||||
assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
return false;
|
||||
return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
|
@ -1290,6 +1290,15 @@ class nmethodBucket: public CHeapObj<mtClass> {
|
||||
nmethodBucket* next() { return _next; }
|
||||
void set_next(nmethodBucket* b) { _next = b; }
|
||||
nmethod* get_nmethod() { return _nmethod; }
|
||||
|
||||
static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes);
|
||||
static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps);
|
||||
#ifndef PRODUCT
|
||||
static void print_dependent_nmethods(nmethodBucket* deps, bool verbose);
|
||||
static bool is_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
#endif //PRODUCT
|
||||
};
|
||||
|
||||
// An iterator that's used to access the inner classes indices in the
|
||||
|
@ -1136,7 +1136,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
|
||||
if (m->has_itable_index()) {
|
||||
// This search must match the runtime resolution, i.e. selection search for invokeinterface
|
||||
// to correctly enforce loader constraints for interface method inheritance
|
||||
LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
|
||||
target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK);
|
||||
}
|
||||
if (target == NULL || !target->is_public() || target->is_abstract()) {
|
||||
// Entry does not resolve. Leave it empty for AbstractMethodError.
|
||||
|
@ -599,10 +599,14 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
const TypeOopPtr* dest_t = phase->type(in(ArrayCopyNode::Dest))->is_oopptr();
|
||||
Node* dest = in(ArrayCopyNode::Dest);
|
||||
if (dest->is_top()) {
|
||||
return false;
|
||||
}
|
||||
const TypeOopPtr* dest_t = phase->type(dest)->is_oopptr();
|
||||
assert(!dest_t->is_known_instance() || _dest_type->is_known_instance(), "result of EA not recorded");
|
||||
const TypeOopPtr* src_t = phase->type(in(ArrayCopyNode::Src))->is_oopptr();
|
||||
assert(!src_t->is_known_instance() || _src_type->is_known_instance(), "result of EA not recorded");
|
||||
assert(in(ArrayCopyNode::Src)->is_top() || !phase->type(in(ArrayCopyNode::Src))->is_oopptr()->is_known_instance() ||
|
||||
_src_type->is_known_instance(), "result of EA not recorded");
|
||||
|
||||
if (_dest_type != TypeOopPtr::BOTTOM || t_oop->is_known_instance()) {
|
||||
assert(_dest_type == TypeOopPtr::BOTTOM || _dest_type->is_known_instance(), "result of EA is known instance");
|
||||
|
@ -1946,7 +1946,7 @@ bool CallLeafNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
|
||||
if (!dest->is_top() && may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1457,18 +1457,18 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) {
|
||||
// factory methods in "int adr_idx"
|
||||
Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
||||
int adr_idx,
|
||||
MemNode::MemOrd mo, bool require_atomic_access) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency, bool require_atomic_access) {
|
||||
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
|
||||
const TypePtr* adr_type = NULL; // debug-mode-only argument
|
||||
debug_only(adr_type = C->get_adr_type(adr_idx));
|
||||
Node* mem = memory(adr_idx);
|
||||
Node* ld;
|
||||
if (require_atomic_access && bt == T_LONG) {
|
||||
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
|
||||
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
||||
} else if (require_atomic_access && bt == T_DOUBLE) {
|
||||
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
|
||||
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
||||
} else {
|
||||
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo);
|
||||
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency);
|
||||
}
|
||||
ld = _gvn.transform(ld);
|
||||
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
|
||||
|
@ -512,21 +512,24 @@ class GraphKit : public Phase {
|
||||
// adapted the `do_put_xxx' and `do_get_xxx' procedures for the case
|
||||
// of volatile fields.
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false) {
|
||||
// This version computes alias_index from bottom_type
|
||||
return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(),
|
||||
mo, require_atomic_access);
|
||||
mo, control_dependency, require_atomic_access);
|
||||
}
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false) {
|
||||
// This version computes alias_index from an address type
|
||||
assert(adr_type != NULL, "use other make_load factory");
|
||||
return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type),
|
||||
mo, require_atomic_access);
|
||||
mo, control_dependency, require_atomic_access);
|
||||
}
|
||||
// This is the base version which is given an alias index.
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false);
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false);
|
||||
|
||||
// Create & transform a StoreNode and store the effect into the
|
||||
// parser's memory state.
|
||||
|
@ -2631,7 +2631,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
|
||||
|
||||
if (!is_store) {
|
||||
MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
|
||||
Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile);
|
||||
// To be valid, unsafe loads may depend on other conditions than
|
||||
// the one that guards them: pin the Load node
|
||||
Node* p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile);
|
||||
// load value
|
||||
switch (type) {
|
||||
case T_BOOLEAN:
|
||||
@ -5488,7 +5490,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field
|
||||
}
|
||||
// Build the load.
|
||||
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
|
||||
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
|
||||
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol);
|
||||
// If reference is volatile, prevent following memory ops from
|
||||
// floating up past the volatile read. Also prevents commoning
|
||||
// another volatile read.
|
||||
|
@ -437,7 +437,13 @@ class Invariance : public StackObj {
|
||||
}
|
||||
}
|
||||
if (all_inputs_invariant) {
|
||||
_invariant.set(n->_idx); // I am a invariant too
|
||||
// If n's control is a predicate that was moved out of the
|
||||
// loop, it was marked invariant but n is only invariant if
|
||||
// it depends only on that test. Otherwise, unless that test
|
||||
// is out of the loop, it's not invariant.
|
||||
if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == NULL || !_phase->is_member(_lpt, n->in(0))) {
|
||||
_invariant.set(n->_idx); // I am a invariant too
|
||||
}
|
||||
}
|
||||
} else { // process next input
|
||||
_stack.set_index(idx + 1);
|
||||
|
@ -1582,13 +1582,36 @@ void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) {
|
||||
if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) {
|
||||
if (!def_node->is_reduction()) { // Not marked yet
|
||||
// To be a reduction, the arithmetic node must have the phi as input and provide a def to it
|
||||
bool ok = false;
|
||||
for (unsigned j = 1; j < def_node->req(); j++) {
|
||||
Node* in = def_node->in(j);
|
||||
if (in == phi) {
|
||||
def_node->add_flag(Node::Flag_is_reduction);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing if we did not match the initial criteria
|
||||
if (ok == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The result of the reduction must not be used in the loop
|
||||
for (DUIterator_Fast imax, i = def_node->fast_outs(imax); i < imax && ok; i++) {
|
||||
Node* u = def_node->fast_out(i);
|
||||
if (has_ctrl(u) && !loop->is_member(get_loop(get_ctrl(u)))) {
|
||||
continue;
|
||||
}
|
||||
if (u == phi) {
|
||||
continue;
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// iff the uses conform
|
||||
if (ok) {
|
||||
def_node->add_flag(Node::Flag_is_reduction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
|
||||
}
|
||||
|
||||
// Use same limit as split_if_with_blocks_post
|
||||
if( C->unique() > 35000 ) return n; // Method too big
|
||||
if( C->live_nodes() > 35000 ) return n; // Method too big
|
||||
|
||||
// Split 'n' through the merge point if it is profitable
|
||||
Node *phi = split_thru_phi( n, n_blk, policy );
|
||||
@ -802,7 +802,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
||||
// Cloning Cmp through Phi's involves the split-if transform.
|
||||
// FastLock is not used by an If
|
||||
if( n->is_Cmp() && !n->is_FastLock() ) {
|
||||
if( C->unique() > 35000 ) return; // Method too big
|
||||
if( C->live_nodes() > 35000 ) return; // Method too big
|
||||
|
||||
// Do not do 'split-if' if irreducible loops are present.
|
||||
if( _has_irreducible_loops )
|
||||
|
@ -844,7 +844,7 @@ void Matcher::init_spill_mask( Node *ret ) {
|
||||
MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
#endif
|
||||
MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
|
||||
MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false));
|
||||
MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false));
|
||||
MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
|
||||
MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
|
||||
MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
|
@ -784,6 +784,9 @@ void LoadNode::dump_spec(outputStream *st) const {
|
||||
// standard dump does this in Verbose and WizardMode
|
||||
st->print(" #"); _type->dump_on(st);
|
||||
}
|
||||
if (!_depends_only_on_test) {
|
||||
st->print(" (does not depend only on test)");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -800,7 +803,7 @@ bool LoadNode::is_immutable_value(Node* adr) {
|
||||
|
||||
//----------------------------LoadNode::make-----------------------------------
|
||||
// Polymorphic factory method:
|
||||
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) {
|
||||
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) {
|
||||
Compile* C = gvn.C;
|
||||
|
||||
// sanity check the alias category against the created node type
|
||||
@ -816,39 +819,39 @@ Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypeP
|
||||
rt->isa_oopptr() || is_immutable_value(adr),
|
||||
"raw memory operations should have control edge");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo);
|
||||
case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo);
|
||||
case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo);
|
||||
case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo);
|
||||
case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency);
|
||||
case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
||||
case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
||||
case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency);
|
||||
case T_OBJECT:
|
||||
#ifdef _LP64
|
||||
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
||||
Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo));
|
||||
Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency));
|
||||
return new DecodeNNode(load, load->bottom_type()->make_ptr());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
|
||||
return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo);
|
||||
return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
|
||||
}
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
return (LoadNode*)NULL;
|
||||
}
|
||||
|
||||
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
|
||||
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
||||
bool require_atomic = true;
|
||||
return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic);
|
||||
return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
|
||||
}
|
||||
|
||||
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
|
||||
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
||||
bool require_atomic = true;
|
||||
return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic);
|
||||
return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,7 +137,33 @@ public:
|
||||
//------------------------------LoadNode---------------------------------------
|
||||
// Load value; requires Memory and Address
|
||||
class LoadNode : public MemNode {
|
||||
public:
|
||||
// Some loads (from unsafe) should be pinned: they don't depend only
|
||||
// on the dominating test. The boolean field _depends_only_on_test
|
||||
// below records whether that node depends only on the dominating
|
||||
// test.
|
||||
// Methods used to build LoadNodes pass an argument of type enum
|
||||
// ControlDependency instead of a boolean because those methods
|
||||
// typically have multiple boolean parameters with default values:
|
||||
// passing the wrong boolean to one of these parameters by mistake
|
||||
// goes easily unnoticed. Using an enum, the compiler can check that
|
||||
// the type of a value and the type of the parameter match.
|
||||
enum ControlDependency {
|
||||
Pinned,
|
||||
DependsOnlyOnTest
|
||||
};
|
||||
private:
|
||||
// LoadNode::hash() doesn't take the _depends_only_on_test field
|
||||
// into account: If the graph already has a non-pinned LoadNode and
|
||||
// we add a pinned LoadNode with the same inputs, it's safe for GVN
|
||||
// to replace the pinned LoadNode with the non-pinned LoadNode,
|
||||
// otherwise it wouldn't be safe to have a non pinned LoadNode with
|
||||
// those inputs in the first place. If the graph already has a
|
||||
// pinned LoadNode and we add a non pinned LoadNode with the same
|
||||
// inputs, it's safe (but suboptimal) for GVN to replace the
|
||||
// non-pinned LoadNode by the pinned LoadNode.
|
||||
bool _depends_only_on_test;
|
||||
|
||||
// On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
|
||||
// loads that can be reordered, and such requiring acquire semantics to
|
||||
// adhere to the Java specification. The required behaviour is stored in
|
||||
@ -154,8 +180,8 @@ protected:
|
||||
virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const;
|
||||
public:
|
||||
|
||||
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo)
|
||||
: MemNode(c,mem,adr,at), _type(rt), _mo(mo) {
|
||||
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency)
|
||||
: MemNode(c,mem,adr,at), _type(rt), _mo(mo), _depends_only_on_test(control_dependency == DependsOnlyOnTest) {
|
||||
init_class_id(Class_Load);
|
||||
}
|
||||
inline bool is_unordered() const { return !is_acquire(); }
|
||||
@ -166,7 +192,8 @@ public:
|
||||
|
||||
// Polymorphic factory method:
|
||||
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
|
||||
const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo);
|
||||
const TypePtr* at, const Type *rt, BasicType bt,
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
|
||||
virtual uint hash() const; // Check the type
|
||||
|
||||
@ -234,16 +261,15 @@ protected:
|
||||
// which produce results (new raw memory state) inside of loops preventing all
|
||||
// manner of other optimizations). Basically, it's ugly but so is the alternative.
|
||||
// See comment in macro.cpp, around line 125 expand_allocate_common().
|
||||
virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
|
||||
|
||||
virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM && _depends_only_on_test; }
|
||||
};
|
||||
|
||||
//------------------------------LoadBNode--------------------------------------
|
||||
// Load a byte (8bits signed) from memory
|
||||
class LoadBNode : public LoadNode {
|
||||
public:
|
||||
LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -256,8 +282,8 @@ public:
|
||||
// Load a unsigned byte (8bits unsigned) from memory
|
||||
class LoadUBNode : public LoadNode {
|
||||
public:
|
||||
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -270,8 +296,8 @@ public:
|
||||
// Load an unsigned short/char (16bits unsigned) from memory
|
||||
class LoadUSNode : public LoadNode {
|
||||
public:
|
||||
LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -284,8 +310,8 @@ public:
|
||||
// Load a short (16bits signed) from memory
|
||||
class LoadSNode : public LoadNode {
|
||||
public:
|
||||
LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -298,8 +324,8 @@ public:
|
||||
// Load an integer from memory
|
||||
class LoadINode : public LoadNode {
|
||||
public:
|
||||
LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual int store_Opcode() const { return Op_StoreI; }
|
||||
@ -331,15 +357,15 @@ class LoadLNode : public LoadNode {
|
||||
|
||||
public:
|
||||
LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl,
|
||||
MemOrd mo, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {}
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, tl, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
virtual int store_Opcode() const { return Op_StoreL; }
|
||||
virtual BasicType memory_type() const { return T_LONG; }
|
||||
bool require_atomic_access() const { return _require_atomic_access; }
|
||||
static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||
const Type* rt, MemOrd mo);
|
||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const {
|
||||
LoadNode::dump_spec(st);
|
||||
@ -352,8 +378,8 @@ public:
|
||||
// Load a long from unaligned memory
|
||||
class LoadL_unalignedNode : public LoadLNode {
|
||||
public:
|
||||
LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
|
||||
: LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {}
|
||||
LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadLNode(c, mem, adr, at, TypeLong::LONG, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
@ -361,8 +387,8 @@ public:
|
||||
// Load a float (64 bits) from memory
|
||||
class LoadFNode : public LoadNode {
|
||||
public:
|
||||
LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegF; }
|
||||
virtual int store_Opcode() const { return Op_StoreF; }
|
||||
@ -382,15 +408,15 @@ class LoadDNode : public LoadNode {
|
||||
|
||||
public:
|
||||
LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t,
|
||||
MemOrd mo, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, t, mo), _require_atomic_access(require_atomic_access) {}
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegD; }
|
||||
virtual int store_Opcode() const { return Op_StoreD; }
|
||||
virtual BasicType memory_type() const { return T_DOUBLE; }
|
||||
bool require_atomic_access() const { return _require_atomic_access; }
|
||||
static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||
const Type* rt, MemOrd mo);
|
||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const {
|
||||
LoadNode::dump_spec(st);
|
||||
@ -403,8 +429,8 @@ public:
|
||||
// Load a double from unaligned memory
|
||||
class LoadD_unalignedNode : public LoadDNode {
|
||||
public:
|
||||
LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
|
||||
: LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {}
|
||||
LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadDNode(c, mem, adr, at, Type::DOUBLE, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
@ -412,8 +438,8 @@ public:
|
||||
// Load a pointer from memory (either object or array)
|
||||
class LoadPNode : public LoadNode {
|
||||
public:
|
||||
LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegP; }
|
||||
virtual int store_Opcode() const { return Op_StoreP; }
|
||||
@ -425,8 +451,8 @@ public:
|
||||
// Load a narrow oop from memory (either object or array)
|
||||
class LoadNNode : public LoadNode {
|
||||
public:
|
||||
LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegN; }
|
||||
virtual int store_Opcode() const { return Op_StoreN; }
|
||||
|
@ -235,7 +235,7 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
|
||||
//
|
||||
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
|
||||
bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
|
||||
Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access);
|
||||
Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access);
|
||||
|
||||
// Adjust Java stack
|
||||
if (type2size[bt] == 1)
|
||||
|
@ -1573,11 +1573,12 @@ void PhaseCCP::analyze() {
|
||||
set_type(n, t);
|
||||
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||
Node* m = n->fast_out(i); // Get user
|
||||
if( m->is_Region() ) { // New path to Region? Must recheck Phis too
|
||||
if (m->is_Region()) { // New path to Region? Must recheck Phis too
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if( p->bottom_type() != type(p) ) // If not already bottomed out
|
||||
if (p->bottom_type() != type(p)) { // If not already bottomed out
|
||||
worklist.push(p); // Propagate change to user
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we changed the receiver type to a call, we need to revisit
|
||||
@ -1587,12 +1588,31 @@ void PhaseCCP::analyze() {
|
||||
if (m->is_Call()) {
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1)
|
||||
if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) {
|
||||
worklist.push(p->unique_out());
|
||||
}
|
||||
}
|
||||
}
|
||||
if( m->bottom_type() != type(m) ) // If not already bottomed out
|
||||
if (m->bottom_type() != type(m)) { // If not already bottomed out
|
||||
worklist.push(m); // Propagate change to user
|
||||
}
|
||||
|
||||
// CmpU nodes can get their type information from two nodes up in the
|
||||
// graph (instead of from the nodes immediately above). Make sure they
|
||||
// are added to the worklist if nodes they depend on are updated, since
|
||||
// they could be missed and get wrong types otherwise.
|
||||
uint m_op = m->Opcode();
|
||||
if (m_op == Op_AddI || m_op == Op_SubI) {
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if (p->Opcode() == Op_CmpU) {
|
||||
// Got a CmpU which might need the new type information from node n.
|
||||
if(p->bottom_type() != type(p)) { // If not already bottomed out
|
||||
worklist.push(p); // Propagate change to user
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1631,7 +1631,7 @@ void SuperWord::output() {
|
||||
}
|
||||
Node* adr = low_adr->in(MemNode::Address);
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n));
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
|
||||
vlen_in_bytes = vn->as_LoadVector()->memory_size();
|
||||
} else if (n->is_Store()) {
|
||||
// Promote value to be stored to vector
|
||||
@ -2280,6 +2280,19 @@ Node* SuperWord::executed_last(Node_List* p) {
|
||||
return n;
|
||||
}
|
||||
|
||||
LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) {
|
||||
LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest;
|
||||
for (uint i = 0; i < p->size(); i++) {
|
||||
Node* n = p->at(i);
|
||||
assert(n->is_Load(), "only meaningful for loads");
|
||||
if (!n->depends_only_on_test()) {
|
||||
dep = LoadNode::Pinned;
|
||||
}
|
||||
}
|
||||
return dep;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------align_initial_loop_index---------------------------
|
||||
// Adjust pre-loop limit so that in main loop, a load/store reference
|
||||
// to align_to_ref will be a position zero in the vector.
|
||||
|
@ -428,6 +428,7 @@ class SuperWord : public ResourceObj {
|
||||
Node* executed_first(Node_List* p);
|
||||
// Return the node executed last in pack p.
|
||||
Node* executed_last(Node_List* p);
|
||||
static LoadNode::ControlDependency control_dependency(Node_List* p);
|
||||
// Alignment within a vector memory reference
|
||||
int memory_alignment(MemNode* s, int iv_adjust);
|
||||
// (Start, end] half-open range defining which operands are vector
|
||||
|
@ -406,9 +406,11 @@ PackNode* PackNode::binary_tree_pack(int lo, int hi) {
|
||||
|
||||
// Return the vector version of a scalar load node.
|
||||
LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem,
|
||||
Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
|
||||
Node* adr, const TypePtr* atyp,
|
||||
uint vlen, BasicType bt,
|
||||
ControlDependency control_dependency) {
|
||||
const TypeVect* vt = TypeVect::make(bt, vlen);
|
||||
return new LoadVectorNode(ctl, mem, adr, atyp, vt);
|
||||
return new LoadVectorNode(ctl, mem, adr, atyp, vt, control_dependency);
|
||||
}
|
||||
|
||||
// Return the vector version of a scalar store node.
|
||||
|
@ -454,8 +454,8 @@ class XorVNode : public VectorNode {
|
||||
// Load Vector from memory
|
||||
class LoadVectorNode : public LoadNode {
|
||||
public:
|
||||
LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt)
|
||||
: LoadNode(c, mem, adr, at, vt, MemNode::unordered) {
|
||||
LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) {
|
||||
init_class_id(Class_LoadVector);
|
||||
}
|
||||
|
||||
@ -471,7 +471,9 @@ class LoadVectorNode : public LoadNode {
|
||||
virtual int store_Opcode() const { return Op_StoreVector; }
|
||||
|
||||
static LoadVectorNode* make(int opc, Node* ctl, Node* mem,
|
||||
Node* adr, const TypePtr* atyp, uint vlen, BasicType bt);
|
||||
Node* adr, const TypePtr* atyp,
|
||||
uint vlen, BasicType bt,
|
||||
ControlDependency control_dependency = LoadNode::DependsOnlyOnTest);
|
||||
};
|
||||
|
||||
//------------------------------StoreVectorNode--------------------------------
|
||||
|
@ -1126,39 +1126,32 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
|
||||
Method* m = Method::resolve_jmethod_id(method_id);
|
||||
number_of_parameters = m->size_of_parameters();
|
||||
Klass* holder = m->method_holder();
|
||||
if (!(holder)->is_interface()) {
|
||||
if (call_type != JNI_VIRTUAL) {
|
||||
selected_method = m;
|
||||
} else if (!m->has_itable_index()) {
|
||||
// non-interface call -- for that little speed boost, don't handlize
|
||||
debug_only(No_Safepoint_Verifier nosafepoint;)
|
||||
if (call_type == JNI_VIRTUAL) {
|
||||
// jni_GetMethodID makes sure class is linked and initialized
|
||||
// so m should have a valid vtable index.
|
||||
assert(!m->has_itable_index(), "");
|
||||
int vtbl_index = m->vtable_index();
|
||||
if (vtbl_index != Method::nonvirtual_vtable_index) {
|
||||
Klass* k = h_recv->klass();
|
||||
// k might be an arrayKlassOop but all vtables start at
|
||||
// the same place. The cast is to avoid virtual call and assertion.
|
||||
InstanceKlass *ik = (InstanceKlass*)k;
|
||||
selected_method = ik->method_at_vtable(vtbl_index);
|
||||
} else {
|
||||
// final method
|
||||
selected_method = m;
|
||||
}
|
||||
// jni_GetMethodID makes sure class is linked and initialized
|
||||
// so m should have a valid vtable index.
|
||||
assert(m->valid_vtable_index(), "no valid vtable index");
|
||||
int vtbl_index = m->vtable_index();
|
||||
if (vtbl_index != Method::nonvirtual_vtable_index) {
|
||||
Klass* k = h_recv->klass();
|
||||
// k might be an arrayKlassOop but all vtables start at
|
||||
// the same place. The cast is to avoid virtual call and assertion.
|
||||
InstanceKlass *ik = (InstanceKlass*)k;
|
||||
selected_method = ik->method_at_vtable(vtbl_index);
|
||||
} else {
|
||||
// JNI_NONVIRTUAL call
|
||||
// final method
|
||||
selected_method = m;
|
||||
}
|
||||
} else {
|
||||
// interface call
|
||||
KlassHandle h_holder(THREAD, holder);
|
||||
|
||||
if (call_type == JNI_VIRTUAL) {
|
||||
int itbl_index = m->itable_index();
|
||||
Klass* k = h_recv->klass();
|
||||
selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
|
||||
} else {
|
||||
selected_method = m;
|
||||
}
|
||||
int itbl_index = m->itable_index();
|
||||
Klass* k = h_recv->klass();
|
||||
selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -842,7 +842,7 @@ JvmtiEnvBase::get_stack_trace(JavaThread *java_thread,
|
||||
// optimize to limit the number of times that java_sender() is called
|
||||
javaVFrame *jvf_cursor = jvf;
|
||||
javaVFrame *jvf_prev = NULL;
|
||||
javaVFrame *jvf_prev_prev;
|
||||
javaVFrame *jvf_prev_prev = NULL;
|
||||
int j = 0;
|
||||
while (jvf_cursor != NULL) {
|
||||
jvf_prev_prev = jvf_prev;
|
||||
|
@ -677,24 +677,24 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
case IS_METHOD:
|
||||
{
|
||||
CallInfo result;
|
||||
LinkInfo link_info(defc, name, type, caller, caller.not_null());
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
if (ref_kind == JVM_REF_invokeStatic) {
|
||||
LinkResolver::resolve_static_call(result,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeInterface) {
|
||||
LinkResolver::resolve_interface_call(result, Handle(), defc,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else if (mh_invoke_id != vmIntrinsics::_none) {
|
||||
assert(!is_signature_polymorphic_static(mh_invoke_id), "");
|
||||
LinkResolver::resolve_handle_call(result,
|
||||
defc, name, type, caller, THREAD);
|
||||
LinkResolver::resolve_handle_call(result, link_info, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeSpecial) {
|
||||
LinkResolver::resolve_special_call(result,
|
||||
defc, name, type, caller, caller.not_null(), THREAD);
|
||||
link_info, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeVirtual) {
|
||||
LinkResolver::resolve_virtual_call(result, Handle(), defc,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else {
|
||||
assert(false, err_msg("ref_kind=%d", ref_kind));
|
||||
}
|
||||
@ -714,11 +714,11 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
case IS_CONSTRUCTOR:
|
||||
{
|
||||
CallInfo result;
|
||||
LinkInfo link_info(defc, name, type, caller, caller.not_null());
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
if (name == vmSymbols::object_initializer_name()) {
|
||||
LinkResolver::resolve_special_call(result,
|
||||
defc, name, type, caller, caller.not_null(), THREAD);
|
||||
LinkResolver::resolve_special_call(result, link_info, THREAD);
|
||||
} else {
|
||||
break; // will throw after end of switch
|
||||
}
|
||||
@ -735,7 +735,8 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
fieldDescriptor result; // find_field initializes fd if found
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
|
||||
LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
|
||||
LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
return empty;
|
||||
}
|
||||
@ -942,22 +943,56 @@ int MethodHandles::find_MemberNames(KlassHandle k,
|
||||
return rfill + overflow;
|
||||
}
|
||||
|
||||
// Get context class for a CallSite instance: either extract existing context or use default one.
|
||||
InstanceKlass* MethodHandles::get_call_site_context(oop call_site) {
|
||||
// In order to extract a context the following traversal is performed:
|
||||
// CallSite.context => Cleaner.referent => Class._klass => Klass
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site);
|
||||
if (oopDesc::is_null(context_oop)) {
|
||||
return NULL; // The context hasn't been initialized yet.
|
||||
void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site);
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
oop context_class_oop = java_lang_ref_Reference::referent(context_oop);
|
||||
if (oopDesc::is_null(context_class_oop)) {
|
||||
// The context reference was cleared by GC, so current dependency context
|
||||
// isn't usable anymore. Context should be fetched from CallSite again.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site);
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
if (nmethodBucket::remove_dependent_nmethod(deps, nm)) {
|
||||
nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) {
|
||||
assert_lock_strong(Compile_lock);
|
||||
|
||||
int marked = 0;
|
||||
CallSiteDepChange changes(call_site(), target());
|
||||
{
|
||||
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site());
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
marked = nmethodBucket::mark_dependent_nmethods(deps, changes);
|
||||
if (marked > 0) {
|
||||
nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1276,7 +1311,7 @@ JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu(Compile_lock, thread);
|
||||
CodeCache::flush_dependents_on(call_site, target);
|
||||
MethodHandles::flush_dependent_nmethods(call_site, target);
|
||||
java_lang_invoke_CallSite::set_target(call_site(), target());
|
||||
}
|
||||
}
|
||||
@ -1288,30 +1323,34 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu(Compile_lock, thread);
|
||||
CodeCache::flush_dependents_on(call_site, target);
|
||||
MethodHandles::flush_dependent_nmethods(call_site, target);
|
||||
java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
|
||||
}
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) {
|
||||
Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
|
||||
JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
|
||||
Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu1(Compile_lock, thread);
|
||||
|
||||
CallSiteDepChange changes(call_site(), Handle());
|
||||
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
|
||||
if (ctxk == NULL) {
|
||||
return; // No dependencies to invalidate yet.
|
||||
}
|
||||
int marked = 0;
|
||||
{
|
||||
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
marked = ctxk->mark_dependent_nmethods(changes);
|
||||
nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
|
||||
while(b != NULL) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) {
|
||||
nm->mark_for_deoptimization();
|
||||
marked++;
|
||||
}
|
||||
nmethodBucket* next = b->next();
|
||||
delete b;
|
||||
b = next;
|
||||
}
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context
|
||||
}
|
||||
java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
@ -1357,6 +1396,7 @@ JVM_END
|
||||
#define MT JLINV"MethodType;"
|
||||
#define MH JLINV"MethodHandle;"
|
||||
#define MEM JLINV"MemberName;"
|
||||
#define CTX JLINV"MethodHandleNatives$CallSiteContext;"
|
||||
|
||||
#define CC (char*) /*cast a literal from (const char*)*/
|
||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
|
||||
@ -1374,7 +1414,7 @@ static JNINativeMethod MHN_methods[] = {
|
||||
{CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)},
|
||||
{CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)},
|
||||
{CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)},
|
||||
{CC"invalidateDependentNMethods", CC"("CS")V", FN_PTR(MHN_invalidateDependentNMethods)},
|
||||
{CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)},
|
||||
{CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)},
|
||||
{CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)},
|
||||
{CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)}
|
||||
|
@ -69,7 +69,10 @@ class MethodHandles: AllStatic {
|
||||
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
|
||||
|
||||
// CallSite support
|
||||
static InstanceKlass* get_call_site_context(oop call_site);
|
||||
static void add_dependent_nmethod(oop call_site, nmethod* nm);
|
||||
static void remove_dependent_nmethod(oop call_site, nmethod* nm);
|
||||
|
||||
static void flush_dependent_nmethods(Handle call_site, Handle target);
|
||||
|
||||
// Generate MethodHandles adapters.
|
||||
static bool generate_adapters();
|
||||
|
@ -64,7 +64,7 @@ void AdvancedThresholdPolicy::initialize() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPARC
|
||||
#if defined SPARC || defined AARCH64
|
||||
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
|
||||
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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
|
||||
@ -179,9 +179,9 @@ void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol*
|
||||
CallInfo callinfo;
|
||||
Handle receiver = args->receiver();
|
||||
KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());
|
||||
LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false);
|
||||
LinkResolver::resolve_virtual_call(
|
||||
callinfo, receiver, recvrKlass, spec_klass, name, signature,
|
||||
KlassHandle(), false, true, CHECK);
|
||||
callinfo, receiver, recvrKlass, link_info, true, CHECK);
|
||||
methodHandle method = callinfo.selected_method();
|
||||
assert(method.not_null(), "should have thrown exception");
|
||||
|
||||
@ -216,7 +216,8 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe
|
||||
|
||||
void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
|
||||
CallInfo callinfo;
|
||||
LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK);
|
||||
LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
|
||||
LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
|
||||
methodHandle method = callinfo.selected_method();
|
||||
assert(method.not_null(), "should have thrown exception");
|
||||
|
||||
@ -250,7 +251,8 @@ void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle kla
|
||||
|
||||
void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
|
||||
CallInfo callinfo;
|
||||
LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK);
|
||||
LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
|
||||
LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK);
|
||||
methodHandle method = callinfo.selected_method();
|
||||
assert(method.not_null(), "should have thrown exception");
|
||||
|
||||
|
@ -775,6 +775,10 @@ void os::start_thread(Thread* thread) {
|
||||
pd_start_thread(thread);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core && CreateCoredumpOnCrash, NULL, NULL);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Helper functions for fatal error handler
|
||||
|
||||
|
@ -831,9 +831,9 @@ methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, metho
|
||||
CallInfo info;
|
||||
Symbol* signature = method->signature();
|
||||
Symbol* name = method->name();
|
||||
LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass,
|
||||
name, signature,
|
||||
KlassHandle(), false, true,
|
||||
LinkResolver::resolve_interface_call(info, receiver, recv_klass,
|
||||
LinkInfo(klass, name, signature, KlassHandle(), false),
|
||||
true,
|
||||
CHECK_(methodHandle()));
|
||||
return info.selected_method();
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ int VMUptimeDCmd::num_arguments() {
|
||||
|
||||
void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
|
||||
if (!DisableExplicitGC) {
|
||||
Universe::heap()->collect(GCCause::_java_lang_system_gc);
|
||||
Universe::heap()->collect(GCCause::_dcmd_gc_run);
|
||||
} else {
|
||||
output()->print_cr("Explicit GC is disabled, no GC has been performed.");
|
||||
}
|
||||
|
@ -89,11 +89,11 @@ private:
|
||||
return ((uintx)1) << validate_tag(tag);
|
||||
}
|
||||
|
||||
static TagType validate_tag(uintx tag) {
|
||||
// Type of tag is not TagType to dodge useless MacOSX compiler warning.
|
||||
assert(tag < (sizeof(uintx) * BitsPerByte),
|
||||
err_msg("Tag " UINTX_FORMAT " is too large", tag));
|
||||
return static_cast<TagType>(tag);
|
||||
static TagType validate_tag(TagType tag) {
|
||||
assert(0 <= tag, err_msg("Tag " INTX_FORMAT " is negative", (intx)tag));
|
||||
assert(tag < BitsPerWord,
|
||||
err_msg("Tag " UINTX_FORMAT " is too large", (uintx)tag));
|
||||
return tag;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8080699
|
||||
* @summary eliminated arraycopy node still reachable through exception edges
|
||||
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestDeadArrayCopyOnMemChain
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestDeadArrayCopyOnMemChain {
|
||||
static class A {
|
||||
int f;
|
||||
}
|
||||
|
||||
static void test_helper(Object o) {
|
||||
}
|
||||
|
||||
static void test(int src_off, boolean flag) {
|
||||
// dst is eliminated first. Eliminating dst causes src to be
|
||||
// eliminated. When working on the safepoint at the uncommon
|
||||
// trap in the exception handler, the eliminated ArrayCopyNode
|
||||
// is reached through the exception edges.
|
||||
Object[] dst = new Object[10];
|
||||
Object[] src = new Object[10];
|
||||
|
||||
// src_off causes the exception handler to be run sometimes
|
||||
try {
|
||||
System.arraycopy(src, src_off, dst, 0, 10);
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
// flag always false so test becomes uncommon trap. Make
|
||||
// sure src is live at the unc.
|
||||
if (flag) {
|
||||
test_helper(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
test((i%2) == 0 ? 0 : -1, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,15 @@
|
||||
/**
|
||||
* @test
|
||||
* @bug 8057967
|
||||
* @ignore 8079205
|
||||
* @run main/bootclasspath -Xbatch java.lang.invoke.CallSiteDepContextTest
|
||||
* @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading
|
||||
* -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
|
||||
* -verbose:gc java.lang.invoke.CallSiteDepContextTest
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.ref.*;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
@ -96,6 +99,13 @@ public class CallSiteDepContextTest {
|
||||
}
|
||||
}
|
||||
|
||||
public static void testHiddenDepField() throws Exception {
|
||||
try {
|
||||
Field f = MethodHandleNatives.CallSiteContext.class.getDeclaredField("vmdependencies");
|
||||
throw new AssertionError("Context.dependencies field should be hidden");
|
||||
} catch(NoSuchFieldException e) { /* expected */ }
|
||||
}
|
||||
|
||||
public static void testSharedCallSite() throws Throwable {
|
||||
Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null);
|
||||
Class<?> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
|
||||
@ -132,12 +142,14 @@ public class CallSiteDepContextTest {
|
||||
static ReferenceQueue rq = new ReferenceQueue();
|
||||
static PhantomReference ref;
|
||||
|
||||
public static void testGC() throws Throwable {
|
||||
public static void testGC(boolean clear, boolean precompile) throws Throwable {
|
||||
String id = "_" + clear + "_" + precompile;
|
||||
|
||||
mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
|
||||
|
||||
Class<?>[] cls = new Class[] {
|
||||
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1"), null),
|
||||
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2"), null),
|
||||
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null),
|
||||
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null),
|
||||
};
|
||||
|
||||
MethodHandle[] mhs = new MethodHandle[] {
|
||||
@ -151,30 +163,38 @@ public class CallSiteDepContextTest {
|
||||
execute(1, mhs);
|
||||
|
||||
ref = new PhantomReference<>(cls[0], rq);
|
||||
cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3"), null);
|
||||
cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null);
|
||||
mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
|
||||
|
||||
do {
|
||||
System.gc();
|
||||
try {
|
||||
Reference ref1 = rq.remove(1000);
|
||||
Reference ref1 = rq.remove(100);
|
||||
if (ref1 == ref) {
|
||||
ref1.clear();
|
||||
System.gc(); // Ensure that the stale context is cleared
|
||||
break;
|
||||
}
|
||||
} catch(InterruptedException e) { /* ignore */ }
|
||||
} while (true);
|
||||
|
||||
execute(1, mhs);
|
||||
if (clear) {
|
||||
ref.clear();
|
||||
System.gc(); // Ensure that the stale context is unloaded
|
||||
}
|
||||
if (precompile) {
|
||||
execute(1, mhs);
|
||||
}
|
||||
mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
|
||||
execute(2, mhs);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
testHiddenDepField();
|
||||
testSharedCallSite();
|
||||
testNonBoundCallSite();
|
||||
testGC();
|
||||
testGC(false, false);
|
||||
testGC(false, true);
|
||||
testGC( true, false);
|
||||
testGC( true, true);
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8080976
|
||||
* @summary Loop variant use in reduction should prevent vectorization
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestReductionWithLoopVariantUse
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestReductionWithLoopVariantUse {
|
||||
static int m(int[] array) {
|
||||
int c = 0;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
c += array[i];
|
||||
array[i] = c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
int[] array = new int[256];
|
||||
int[] array2 = new int[256];
|
||||
for (int j = 0; j < 256; j++) {
|
||||
array2[j] = j;
|
||||
}
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
System.arraycopy(array2, 0, array, 0, 256);
|
||||
int res = m(array);
|
||||
boolean success = true;
|
||||
int c = 0;
|
||||
for (int j = 0; j < 256; j++) {
|
||||
c += array2[j];
|
||||
if (array[j] != c) {
|
||||
System.out.println("Failed for " + j + " : " + array[j] + " != " + c);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (c != res) {
|
||||
System.out.println("Failed for sum: " + c + " != " + res);
|
||||
}
|
||||
if (!success) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
59
hotspot/test/compiler/types/TestTypePropagationToCmpU.java
Normal file
59
hotspot/test/compiler/types/TestTypePropagationToCmpU.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8080156 8060036
|
||||
* @summary Test correctness of type propagation to CmpUNodes.
|
||||
* @run main TestTypePropagationToCmpU
|
||||
*/
|
||||
public class TestTypePropagationToCmpU {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// Trigger compilation
|
||||
for (int i = 0; i < 100_000; ++i) {
|
||||
test();
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
// Test should never throw a NullPointerException
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
|
||||
static int global = 42;
|
||||
|
||||
public static void test() {
|
||||
int a = Integer.MIN_VALUE;
|
||||
int b = global;
|
||||
char[] buf = { 0 };
|
||||
for (int i = 0; i <= b; ++i) {
|
||||
a = i - b;
|
||||
}
|
||||
// C2 adds a range check and an uncommon trap here to ensure that the array index
|
||||
// is in bounds. If type information is not propagated correctly to the corresponding
|
||||
// CmpUNode, this trap may be always taken. Because C2 also removes the unnecessary
|
||||
// allocation of 'buf', a NullPointerException is thrown in this case.
|
||||
char c = buf[(a * 11) / 2 - a]; // a is 0 here if global >= 0
|
||||
buf[0] = 0;
|
||||
}
|
||||
}
|
103
hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
Normal file
103
hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077504
|
||||
* @summary Unsafe load can loose control dependency and cause crash
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestUnsafeLoadControl
|
||||
*
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class TestUnsafeLoadControl {
|
||||
|
||||
private static final Unsafe UNSAFE;
|
||||
|
||||
static {
|
||||
try {
|
||||
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
UNSAFE = (Unsafe) unsafeField.get(null);
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static int val;
|
||||
static void test1(int[] a, boolean[] flags, boolean flag, long j) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (flags[i]) {
|
||||
if (flag) {
|
||||
long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
|
||||
int v = UNSAFE.getInt(a, address);
|
||||
val = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int test2(int[] a, boolean[] flags, boolean flag, long j) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (flags[i]) {
|
||||
if (flag) {
|
||||
long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
|
||||
int v = UNSAFE.getInt(a, address);
|
||||
if (v == 0) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
boolean[] flags = new boolean[10];
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
flags[i] = true;
|
||||
}
|
||||
int[] array = new int[10];
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
test1(array, flags, true, 0);
|
||||
}
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
flags[i] = false;
|
||||
}
|
||||
test1(array, flags, true, Long.MAX_VALUE/4);
|
||||
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
flags[i] = true;
|
||||
}
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
test2(array, flags, true, 0);
|
||||
}
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
flags[i] = false;
|
||||
}
|
||||
test2(array, flags, true, Long.MAX_VALUE/4);
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@
|
||||
* @requires vm.gc=="null"
|
||||
* @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
|
||||
* @requires vm.compMode != "Xcomp"
|
||||
* @requires vm.opt.UseCompressedOops != false
|
||||
* @summary Verify that starting the VM with a small heap works
|
||||
* @library /testlibrary /../../test/lib
|
||||
* @modules java.management/sun.management
|
||||
|
@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
* 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
|
||||
@ -22,12 +20,27 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.tools.sjavac.comp.dependencies;
|
||||
|
||||
import java.util.Set;
|
||||
/**
|
||||
* Implementation of InterfaceWithToString.
|
||||
*/
|
||||
public class ImplementationOfWithToString implements InterfaceWithToString {
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
/**
|
||||
* @see InterfaceWithToString#someMethod()
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void someMethod() {
|
||||
// May do something here.
|
||||
}
|
||||
|
||||
interface Dependency {
|
||||
Set<PackageSymbol> getPackages();
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "toString() from " + getClass().getName();
|
||||
}
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
* 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
|
||||
@ -22,7 +20,18 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package pkg25;
|
||||
|
||||
public class Cls25 extends Throwable {
|
||||
/**
|
||||
* Interface with toString declared.
|
||||
*/
|
||||
public interface InterfaceWithToString {
|
||||
|
||||
void someMethod();
|
||||
|
||||
/**
|
||||
* Same as Object.toString().
|
||||
*
|
||||
* @return some custom string.
|
||||
*/
|
||||
String toString();
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
* 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
|
||||
@ -22,9 +20,22 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package pkg13;
|
||||
public class Cls13 {
|
||||
public pkg14.Cls14 getCls14() {
|
||||
return null;
|
||||
|
||||
/* @test
|
||||
* @bug 8072588
|
||||
* @build InterfaceWithToString
|
||||
* @build ImplementationOfWithToString
|
||||
* @run main/native ToStringTest
|
||||
*/
|
||||
public final class ToStringTest {
|
||||
|
||||
static {
|
||||
System.loadLibrary("ToStringTest");
|
||||
}
|
||||
|
||||
native static void nTest();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
nTest();
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Native test for ToStringInInterfaceTest.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#define checkException(env) if ((*env)->ExceptionCheck(env)) { return; }
|
||||
|
||||
jstring callStringMethod(JNIEnv* env, jobject jobj, jmethodID id, ...)
|
||||
{
|
||||
jstring value;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, id);
|
||||
value = (jstring)(*env)->CallObjectMethodV(env, jobj, id, ap);
|
||||
va_end(ap);
|
||||
return value;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_ToStringTest_nTest(JNIEnv* env, jclass jclazz)
|
||||
{
|
||||
jclass classOfInterfaceWithToString;
|
||||
jclass classOfImplementationOfWithToString;
|
||||
jmethodID constructorOfImplementationOfWithToString;
|
||||
jobject instanceOfImplementationOfWithToString;
|
||||
jmethodID toStringOfInterfaceWithToString;
|
||||
jmethodID toStringOfImplementationOfWithToString;
|
||||
jstring jstr;
|
||||
const char *chars;
|
||||
|
||||
classOfInterfaceWithToString = (*env)->FindClass(env, "InterfaceWithToString");
|
||||
checkException(env);
|
||||
classOfImplementationOfWithToString = (*env)->FindClass(env, "ImplementationOfWithToString");
|
||||
checkException(env);
|
||||
|
||||
constructorOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "<init>", "()V");
|
||||
checkException(env);
|
||||
|
||||
instanceOfImplementationOfWithToString = (*env)->NewObject(env, classOfImplementationOfWithToString, constructorOfImplementationOfWithToString);
|
||||
checkException(env);
|
||||
|
||||
toStringOfInterfaceWithToString = (*env)->GetMethodID(env, classOfInterfaceWithToString, "toString", "()Ljava/lang/String;");
|
||||
checkException(env);
|
||||
|
||||
toStringOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "toString", "()Ljava/lang/String;");
|
||||
checkException(env);
|
||||
|
||||
jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfImplementationOfWithToString);
|
||||
checkException(env);
|
||||
|
||||
chars = (*env)->GetStringUTFChars(env, jstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, jstr, chars);
|
||||
|
||||
jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfInterfaceWithToString);
|
||||
checkException(env);
|
||||
|
||||
chars = (*env)->GetStringUTFChars(env, jstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, jstr, chars);
|
||||
}
|
@ -59,7 +59,7 @@ public class RunGCTest {
|
||||
}
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(gcLog, "");
|
||||
output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*");
|
||||
output.shouldContain("[Full GC (Diagnostic Command)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -24,11 +24,14 @@
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /../../test/lib/share/classes
|
||||
* @library /testlibrary
|
||||
* @build jdk.test.lib.*
|
||||
* @build jdk.test.lib.apps.*
|
||||
* @run main TestClassLoaderStats
|
||||
*/
|
||||
public class TestClassLoaderStats {
|
||||
@ -39,19 +42,27 @@ public class TestClassLoaderStats {
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UsePerfData",
|
||||
"sun.jvm.hotspot.tools.ClassLoaderStats",
|
||||
Integer.toString(ProcessTools.getProcessId()));
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
|
||||
System.out.println(output.getOutput());
|
||||
LingeredApp app = null;
|
||||
try {
|
||||
app = LingeredApp.startApp();
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
output.shouldContain("Debugger attached successfully.");
|
||||
// The class loader stats header needs to be presented in the output:
|
||||
output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
|
||||
output.stderrShouldNotMatch("[E|e]xception");
|
||||
output.stderrShouldNotMatch("[E|e]rror");
|
||||
System.out.println("Attaching sun.jvm.hotspot.tools.ClassLoaderStats to " + app.getPid());
|
||||
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UsePerfData",
|
||||
"sun.jvm.hotspot.tools.ClassLoaderStats",
|
||||
Long.toString(app.getPid()));
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
|
||||
System.out.println(output.getOutput());
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
output.shouldContain("Debugger attached successfully.");
|
||||
// The class loader stats header needs to be presented in the output:
|
||||
output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
|
||||
output.stderrShouldNotMatch("[E|e]xception");
|
||||
output.stderrShouldNotMatch("[E|e]rror");
|
||||
} finally {
|
||||
app.stopApp();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,11 +24,14 @@
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /../../test/lib/share/classes
|
||||
* @library /testlibrary
|
||||
* @build jdk.test.lib.*
|
||||
* @build jdk.test.lib.apps.*
|
||||
* @run main TestStackTrace
|
||||
*/
|
||||
public class TestStackTrace {
|
||||
@ -39,17 +42,25 @@ public class TestStackTrace {
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UsePerfData",
|
||||
"sun.jvm.hotspot.tools.StackTrace",
|
||||
Integer.toString(ProcessTools.getProcessId()));
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
|
||||
System.out.println(output.getOutput());
|
||||
LingeredApp app = null;
|
||||
try {
|
||||
app = LingeredApp.startApp();
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
output.shouldContain("Debugger attached successfully.");
|
||||
output.stderrShouldNotMatch("[E|e]xception");
|
||||
output.stderrShouldNotMatch("[E|e]rror");
|
||||
System.out.println("Attaching sun.jvm.hotspot.tools.StackTrace to " + app.getPid());
|
||||
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UsePerfData",
|
||||
"sun.jvm.hotspot.tools.StackTrace",
|
||||
Long.toString(app.getPid()));
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
|
||||
System.out.println(output.getOutput());
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
output.shouldContain("Debugger attached successfully.");
|
||||
output.stderrShouldNotMatch("[E|e]xception");
|
||||
output.stderrShouldNotMatch("[E|e]rror");
|
||||
} finally {
|
||||
app.stopApp();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -310,3 +310,4 @@ f4a4a54620370f077c2e830a5561c8cfa811712b jdk9-b61
|
||||
ae7406e82828fe1c245ac7507a9da5fd5b1c9529 jdk9-b65
|
||||
d5963ccce28d7a3e96ee3e2dc8a8676e61699b70 jdk9-b66
|
||||
78c2685daabafae827c686ca2d1bb2e451faed2b jdk9-b67
|
||||
82aae947938ec9b0119fdd78a616d0b7263072ee jdk9-b68
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user