This commit is contained in:
Harold Seigel 2014-01-29 19:54:44 -05:00
commit b7100718e8
13 changed files with 256 additions and 49 deletions

@ -64,7 +64,7 @@ MFLAGS=`
echo "$MFLAGS" \
| sed '
s/^-/ -/
s/ -\([^ ][^ ]*\)j/ -\1 -j/
s/ -\([^ I][^ I]*\)j/ -\1 -j/
s/ -j[0-9][0-9]*/ -j/
s/ -j\([^ ]\)/ -j -\1/
s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/

@ -64,7 +64,7 @@ MFLAGS=`
echo "$MFLAGS" \
| sed '
s/^-/ -/
s/ -\([^ ][^ ]*\)j/ -\1 -j/
s/ -\([^ I][^ I]*\)j/ -\1 -j/
s/ -j[0-9][0-9]*/ -j/
s/ -j\([^ ]\)/ -j -\1/
s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/

@ -64,7 +64,7 @@ MFLAGS=`
echo "$MFLAGS" \
| sed '
s/^-/ -/
s/ -\([^ ][^ ]*\)j/ -\1 -j/
s/ -\([^ I][^ I]*\)j/ -\1 -j/
s/ -j[0-9][0-9]*/ -j/
s/ -j\([^ ]\)/ -j -\1/
s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/

@ -3361,8 +3361,8 @@ operand immI16() %{
interface(CONST_INTER);
%}
// Unsigned (positive) Integer Immediate: 13-bit
operand immU13() %{
// 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);
@ -3398,6 +3398,17 @@ operand immI5() %{
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);
@ -5726,7 +5737,6 @@ instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
size((3+1)*4); // set may use two instructions.
format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
@ -5848,13 +5858,13 @@ instruct loadI2L_immI_65535(iRegL dst, indOffset13m7 mem, immI_65535 mask) %{
ins_pipe(iload_mem);
%}
// Load Integer with a 13-bit mask into a Long Register
instruct loadI2L_immI13(iRegL dst, memory mem, immI13 mask) %{
// Load Integer with a 12-bit mask into a Long Register
instruct loadI2L_immU12(iRegL dst, memory mem, immU12 mask) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
size(2*4);
format %{ "LDUW $mem,$dst\t! int & 13-bit mask -> long\n\t"
format %{ "LDUW $mem,$dst\t! int & 12-bit mask -> long\n\t"
"AND $dst,$mask,$dst" %}
ins_encode %{
Register Rdst = $dst$$Register;
@ -5864,14 +5874,13 @@ instruct loadI2L_immI13(iRegL dst, memory mem, immI13 mask) %{
ins_pipe(iload_mem);
%}
// Load Integer with a 32-bit mask into a Long Register
instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
// Load Integer with a 31-bit mask into a Long Register
instruct loadI2L_immU31(iRegL dst, memory mem, immU31 mask, iRegL tmp) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
size((3+1)*4); // set may use two instructions.
format %{ "LDUW $mem,$dst\t! int & 32-bit mask -> long\n\t"
format %{ "LDUW $mem,$dst\t! int & 31-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
ins_encode %{
@ -8966,7 +8975,7 @@ instruct testL_reg_con(flagsRegL xcc, iRegL op1, immL13 con, immL0 zero) %{
ins_pipe(ialu_cconly_reg_reg);
%}
instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU13 op2 ) %{
instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{
match(Set icc (CmpU op1 op2));
size(4);

@ -3889,6 +3889,17 @@ operand immI16() %{
interface(CONST_INTER);
%}
// Int Immediate non-negative
operand immU31()
%{
predicate(n->get_int() >= 0);
match(ConI);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
// Constant for long shifts
operand immI_32() %{
predicate( n->get_int() == 32 );
@ -6119,12 +6130,12 @@ instruct loadI2L_immI_65535(eRegL dst, memory mem, immI_65535 mask, eFlagsReg cr
ins_pipe(ialu_reg_mem);
%}
// Load Integer with 32-bit mask into Long Register
instruct loadI2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
// Load Integer with 31-bit mask into Long Register
instruct loadI2L_immU31(eRegL dst, memory mem, immU31 mask, eFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(KILL cr);
format %{ "MOV $dst.lo,$mem\t# int & 32-bit mask -> long\n\t"
format %{ "MOV $dst.lo,$mem\t# int & 31-bit mask -> long\n\t"
"XOR $dst.hi,$dst.hi\n\t"
"AND $dst.lo,$mask" %}
ins_encode %{

@ -3086,6 +3086,17 @@ operand immI16()
interface(CONST_INTER);
%}
// Int Immediate non-negative
operand immU31()
%{
predicate(n->get_int() >= 0);
match(ConI);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
// Constant for long shifts
operand immI_32()
%{
@ -5042,12 +5053,12 @@ instruct loadI2L_immI_65535(rRegL dst, memory mem, immI_65535 mask) %{
ins_pipe(ialu_reg_mem);
%}
// Load Integer with a 32-bit mask into Long Register
instruct loadI2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
// Load Integer with a 31-bit mask into Long Register
instruct loadI2L_immU31(rRegL dst, memory mem, immU31 mask, rFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(KILL cr);
format %{ "movl $dst, $mem\t# int & 32-bit mask -> long\n\t"
format %{ "movl $dst, $mem\t# int & 31-bit mask -> long\n\t"
"andl $dst, $mask" %}
ins_encode %{
Register Rdst = $dst$$Register;

@ -1221,11 +1221,9 @@ bool Dependencies::is_concrete_method(Method* m) {
// We could also return false if m does not yet appear to be
// executed, if the VM version supports this distinction also.
// Default methods are considered "concrete" as well.
return !m->is_abstract() &&
!InstanceKlass::cast(m->method_holder())->is_interface();
// TODO: investigate whether default methods should be
// considered as "concrete" in this situation. For now they
// are not.
!m->is_overpass(); // error functions aren't concrete
}

@ -175,8 +175,8 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) {
oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
assert(info.resolved_appendix().is_null(), "only normal methods here");
KlassHandle receiver_limit = info.resolved_klass();
methodHandle m = info.resolved_method();
KlassHandle m_klass = m->method_holder();
int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
int vmindex = Method::invalid_vtable_index;
@ -184,14 +184,13 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
case CallInfo::itable_call:
vmindex = info.itable_index();
// More importantly, the itable index only works with the method holder.
receiver_limit = m->method_holder();
assert(receiver_limit->verify_itable_index(vmindex), "");
assert(m_klass->verify_itable_index(vmindex), "");
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
if (TraceInvokeDynamic) {
ResourceMark rm;
tty->print_cr("memberName: invokeinterface method_holder::method: %s, receiver: %s, itableindex: %d, access_flags:",
Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
receiver_limit()->internal_name(), vmindex);
tty->print_cr("memberName: invokeinterface method_holder::method: %s, itableindex: %d, access_flags:",
Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()),
vmindex);
m->access_flags().print_on(tty);
if (!m->is_abstract()) {
tty->print("default");
@ -203,12 +202,35 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
case CallInfo::vtable_call:
vmindex = info.vtable_index();
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
assert(info.resolved_klass()->is_subtype_of(m_klass()), "virtual call must be type-safe");
if (m_klass->is_interface()) {
// This is a vtable call to an interface method (abstract "miranda method" or default method).
// The vtable index is meaningless without a class (not interface) receiver type, so get one.
// (LinkResolver should help us figure this out.)
KlassHandle m_klass_non_interface = info.resolved_klass();
if (m_klass_non_interface->is_interface()) {
m_klass_non_interface = SystemDictionary::Object_klass();
#ifdef ASSERT
{ ResourceMark rm;
Method* m2 = m_klass_non_interface->vtable()->method_at(vmindex);
assert(m->name() == m2->name() && m->signature() == m2->signature(),
err_msg("at %d, %s != %s", vmindex,
m->name_and_sig_as_C_string(), m2->name_and_sig_as_C_string()));
}
#endif //ASSERT
}
if (!m->is_public()) {
assert(m->is_public(), "virtual call must be to public interface method");
return NULL; // elicit an error later in product build
}
assert(info.resolved_klass()->is_subtype_of(m_klass_non_interface()), "virtual call must be type-safe");
m_klass = m_klass_non_interface;
}
if (TraceInvokeDynamic) {
ResourceMark rm;
tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:",
Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
receiver_limit()->internal_name(), vmindex);
Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()),
m_klass->internal_name(), vmindex);
m->access_flags().print_on(tty);
if (m->is_default_method()) {
tty->print("default");
@ -223,10 +245,8 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
} else if (m->is_initializer()) {
flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed");
} else {
flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe");
}
break;
@ -242,7 +262,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
java_lang_invoke_MemberName::set_flags( mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, m());
java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index
java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror());
java_lang_invoke_MemberName::set_clazz( mname_oop, m_klass->java_mirror());
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and MethodType objects.
// The clazz must be eagerly stored, because it provides a GC
@ -569,7 +589,7 @@ oop MethodHandles::field_signature_type_or_null(Symbol* s) {
// An unresolved member name is a mere symbolic reference.
// Resolving it plants a vmtarget/vmindex in it,
// which refers directly to JVM internals.
Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS) {
Handle empty;
assert(java_lang_invoke_MemberName::is_instance(mname()), "");
@ -646,20 +666,20 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
assert(!HAS_PENDING_EXCEPTION, "");
if (ref_kind == JVM_REF_invokeStatic) {
LinkResolver::resolve_static_call(result,
defc, name, type, KlassHandle(), false, false, THREAD);
defc, name, type, caller, caller.not_null(), false, THREAD);
} else if (ref_kind == JVM_REF_invokeInterface) {
LinkResolver::resolve_interface_call(result, Handle(), defc,
defc, name, type, KlassHandle(), false, false, THREAD);
defc, name, type, caller, caller.not_null(), 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, KlassHandle(), THREAD);
defc, name, type, caller, THREAD);
} else if (ref_kind == JVM_REF_invokeSpecial) {
LinkResolver::resolve_special_call(result,
defc, name, type, KlassHandle(), false, THREAD);
defc, name, type, caller, caller.not_null(), THREAD);
} else if (ref_kind == JVM_REF_invokeVirtual) {
LinkResolver::resolve_virtual_call(result, Handle(), defc,
defc, name, type, KlassHandle(), false, false, THREAD);
defc, name, type, caller, caller.not_null(), false, THREAD);
} else {
assert(false, err_msg("ref_kind=%d", ref_kind));
}
@ -683,7 +703,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
assert(!HAS_PENDING_EXCEPTION, "");
if (name == vmSymbols::object_initializer_name()) {
LinkResolver::resolve_special_call(result,
defc, name, type, KlassHandle(), false, THREAD);
defc, name, type, caller, caller.not_null(), THREAD);
} else {
break; // will throw after end of switch
}
@ -700,7 +720,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
fieldDescriptor result; // find_field initializes fd if found
{
assert(!HAS_PENDING_EXCEPTION, "");
LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD);
LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
return empty;
}
@ -1121,7 +1141,11 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh,
}
}
Handle resolved = MethodHandles::resolve_MemberName(mname, CHECK_NULL);
KlassHandle caller(THREAD,
caller_jh == NULL ? (Klass*) NULL :
java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)));
Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL);
if (resolved.is_null()) {
int flags = java_lang_invoke_MemberName::flags(mname());
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;

@ -55,7 +55,7 @@ class MethodHandles: AllStatic {
public:
// working with member names
static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
static Handle resolve_MemberName(Handle mname, KlassHandle caller, TRAPS); // compute vmtarget/vmindex from name/type
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static Handle new_MemberName(TRAPS); // must be followed by init_MemberName
static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target

@ -1262,9 +1262,6 @@ bool os::set_boot_path(char fileSep, char pathSep) {
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/lib/jfr.jar:"
#ifdef __APPLE__
"%/lib/JObjC.jar:"
#endif
"%/classes";
char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
if (sysclasspath == NULL) return false;

@ -0,0 +1,44 @@
/*
* 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.
*
* 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 8032207
* @summary Invalid node sizing for loadUS2L_immI16 and loadI2L_immI
* @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,LoadWithMask.foo LoadWithMask
*
*/
public class LoadWithMask {
static int x[] = new int[1];
static long foo() {
return x[0] & 0xfff0ffff;
}
public static void main(String[] args) {
x[0] = -1;
long l = 0;
for (int i = 0; i < 100000; ++i) {
l = foo();
}
}
}

@ -0,0 +1,55 @@
/*
* 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.
*
* 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 8031743
* @summary loadI2L_immI broken for negative memory values
* @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,*.foo* LoadWithMask2
*
*/
public class LoadWithMask2 {
static int x;
static long foo1() {
return x & 0xfffffffe;
}
static long foo2() {
return x & 0xff000000;
}
static long foo3() {
return x & 0x8abcdef1;
}
public static void main(String[] args) {
x = -1;
long l = 0;
for (int i = 0; i < 100000; ++i) {
l = foo1() & foo2() & foo3();
}
if (l > 0) {
System.out.println("FAILED");
System.exit(97);
}
System.out.println("PASSED");
}
}

@ -0,0 +1,58 @@
/*
* 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.
*
* 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 8031695
* @summary CHA ignores default methods during analysis leading to incorrect code generation
*
* @run main/othervm -Xbatch DefaultAndConcreteMethodsCHA
*/
interface I {
default int m() { return 0; }
}
class A implements I {}
class C extends A { }
class D extends A { public int m() { return 1; } }
public class DefaultAndConcreteMethodsCHA {
public static int test(A obj) {
return obj.m();
}
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
int idC = test(new C());
if (idC != 0) {
throw new Error("C.m didn't invoke I.m: id "+idC);
}
int idD = test(new D());
if (idD != 1) {
throw new Error("D.m didn't invoke D.m: id "+idD);
}
}
}
}