8144466: ppc64: fix argument passing through opto stubs

Reviewed-by: kvn
This commit is contained in:
Goetz Lindenmaier 2015-12-07 15:42:47 +01:00
parent 223668aab4
commit 6f27a97d77
10 changed files with 229 additions and 22 deletions

@ -46,6 +46,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
#
# Add conditional directories here when needed.

@ -28,6 +28,10 @@
const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are extended to 64 bits.
const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
// The maximum B/BL offset range on AArch64 is 128MB.

@ -31,6 +31,10 @@ const int BytesPerInstWord = 4;
const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are extended to 64 bits.
const bool CCallingConventionRequiresIntsAsLongs = true;
#define SUPPORTS_NATIVE_CX8
// The PPC CPUs are NOT multiple-copy-atomic.

@ -30,6 +30,10 @@ const int BytesPerInstWord = 4;
const int StackAlignmentInBytes = (2*wordSize);
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are extended to 64 bits.
const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
// The expected size in bytes of a cache line, used to pad data structures.

@ -27,6 +27,10 @@
const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are extended to 64 bits.
const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
// The expected size in bytes of a cache line, used to pad data structures.

@ -28,4 +28,8 @@
#include <ffi.h>
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are extended to 64 bits.
const bool CCallingConventionRequiresIntsAsLongs = false;
#endif // CPU_ZERO_VM_GLOBALDEFINITIONS_ZERO_HPP

@ -72,16 +72,18 @@ void GraphKit::gen_stub(address C_function,
// Make up the parameters
uint i;
for( i = 0; i < parm_cnt; i++ )
for (i = 0; i < parm_cnt; i++) {
map()->init_req(i, _gvn.transform(new ParmNode(start, i)));
for( ; i<map()->req(); i++ )
}
for ( ; i<map()->req(); i++) {
map()->init_req(i, top()); // For nicer debugging
}
// GraphKit requires memory to be a MergeMemNode:
set_all_memory(map()->memory());
// Get base of thread-local storage area
Node* thread = _gvn.transform( new ThreadLocalNode() );
Node* thread = _gvn.transform(new ThreadLocalNode());
const int NoAlias = Compile::AliasIdxBot;
@ -113,21 +115,27 @@ void GraphKit::gen_stub(address C_function,
//-----------------------------
// Compute signature for C call. Varies from the Java signature!
const Type **fields = TypeTuple::fields(2*parm_cnt+2);
uint cnt = TypeFunc::Parms;
// The C routines gets the base of thread-local storage passed in as an
// extra argument. Not all calls need it, but its cheap to add here.
// extra argument. Not all calls need it, but it is cheap to add here.
for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) {
fields[cnt] = jdomain->field_at(pcnt);
const Type *f = jdomain->field_at(pcnt);
if (CCallingConventionRequiresIntsAsLongs && f->isa_int()) {
fields[cnt++] = TypeLong::LONG;
fields[cnt] = Type::HALF; // Must add an additional half for a long.
} else {
fields[cnt] = f;
}
}
fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage
// Also pass in the caller's PC, if asked for.
if (return_pc) {
fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC
}
const TypeTuple* domain = TypeTuple::make(cnt, fields);
const TypeTuple* domain = TypeTuple::make(cnt,fields);
// The C routine we are about to call cannot return an oop; it can block on
// exit and a GC will trash the oop while it sits in C-land. Instead, we
// return the oop through TLS for runtime calls.
@ -155,37 +163,44 @@ void GraphKit::gen_stub(address C_function,
rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1);
}
}
const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields);
const TypeTuple* range = TypeTuple::make(jrange->cnt(), rfields);
// Final C signature
const TypeFunc *c_sig = TypeFunc::make(domain,range);
const TypeFunc *c_sig = TypeFunc::make(domain, range);
//-----------------------------
// Make the call node
// Make the call node.
CallRuntimeNode *call = new CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM);
//-----------------------------
// Fix-up the debug info for the call
call->set_jvms( new (C) JVMState(0) );
// Fix-up the debug info for the call.
call->set_jvms(new (C) JVMState(0));
call->jvms()->set_bci(0);
call->jvms()->set_offsets(cnt);
// Set fixed predefined input arguments
// Set fixed predefined input arguments.
cnt = 0;
for (i = 0; i < TypeFunc::Parms; i++)
call->init_req(cnt++, map()->in(i));
// A little too aggressive on the parm copy; return address is not an input
call->set_req(TypeFunc::ReturnAdr, top());
for (; i < parm_cnt; i++) { // Regular input arguments
for (i = 0; i < TypeFunc::Parms; i++) {
call->init_req(cnt++, map()->in(i));
}
// A little too aggressive on the parm copy; return address is not an input.
call->set_req(TypeFunc::ReturnAdr, top());
for (; i < parm_cnt; i++) { // Regular input arguments.
const Type *f = jdomain->field_at(i);
if (CCallingConventionRequiresIntsAsLongs && f->isa_int()) {
call->init_req(cnt++, _gvn.transform(new ConvI2LNode(map()->in(i))));
call->init_req(cnt++, top());
} else {
call->init_req(cnt++, map()->in(i));
}
}
call->init_req(cnt++, thread);
if (return_pc) { // Return PC, if asked for.
call->init_req(cnt++, returnadr());
}
call->init_req( cnt++, thread );
if( return_pc ) // Return PC, if asked for
call->init_req( cnt++, returnadr() );
_gvn.transform_no_reclaim(call);
//-----------------------------
// Now set up the return results
set_control( _gvn.transform( new ProjNode(call,TypeFunc::Control)) );

@ -0,0 +1,69 @@
/*
* Copyright (c) 2015 SAP SE. 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
* @summary Test that overflowed integers passed to arraycopy don't do any harm. This might
* be the case on platforms where C-code expects that ints passed to a call
* are properly sign extended to 64 bit (e.g., PPC64, s390x). This can fail
* if slow_arraycopy_C() is commpiled by the C compiler without any imlicit
* casts (as spill stores to the stack that are done with 4-byte instruction).
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyOverflowArguments
*
*/
public class TestArrayCopyOverflowArguments {
// Without volatile the overflowing computation was moved up and then
// spilled to the stack. The 32-bit spill store caused proper rounding.
static volatile int mod = Integer.MAX_VALUE;
public static int[] m1(Object src) {
if (src == null) return null;
int[] dest = new int[10];
try {
// PPC C calling conventions require that ints are properly expanded
// to longs when passed to a function.
int pos = 8 + mod + mod; // = 0x1_0000_0006.
int start = 2 + mod + mod; // = 0x1_0000_0000.
int len = 12 + mod + mod; // = 0x1_0000_0010.
// This is supposed to call SharedRuntime::slow_arraycopy_C().
System.arraycopy(src, pos, dest, 0, 10);
} catch (ArrayStoreException npe) {
}
return dest;
}
static public void main(String[] args) throws Exception {
int[] src = new int[20];
for (int i = 0; i < 20; ++i) {
src[i] = i * (i-1);
}
for (int i = 0; i < 20000; i++) {
m1(src);
}
}
}

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015 SAP SE. 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 8139258
* @summary Regression test for 8139258 which failed to properly pass float args
* to a jni function on ppc64le.
* @run main/othervm -Xint Test15FloatJNIArgs
* @run main/othervm -XX:+TieredCompilation -Xcomp Test15FloatJNIArgs
* @run main/othervm -XX:-TieredCompilation -Xcomp Test15FloatJNIArgs
*/
public class Test15FloatJNIArgs {
static {
try {
System.loadLibrary("Test15FloatJNIArgs");
} catch (UnsatisfiedLinkError e) {
System.out.println("could not load native lib: " + e);
}
}
public static native float add15floats(
float f1, float f2, float f3, float f4,
float f5, float f6, float f7, float f8,
float f9, float f10, float f11, float f12,
float f13, float f14, float f15);
static void test() throws Exception {
float sum = Test15FloatJNIArgs.add15floats(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
if (sum != 15.0f) {
throw new Error("Passed 15 times 1.0f to jni function which didn't add them properly: " + sum);
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 200; ++i) {
test();
}
}
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2015. 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.
*/
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jfloat JNICALL Java_Test15FloatJNIArgs_add15floats
(JNIEnv *env, jclass cls,
jfloat f1, jfloat f2, jfloat f3, jfloat f4,
jfloat f5, jfloat f6, jfloat f7, jfloat f8,
jfloat f9, jfloat f10, jfloat f11, jfloat f12,
jfloat f13, jfloat f14, jfloat f15) {
return f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15;
}
#ifdef __cplusplus
}
#endif