8331935: Add support for primitive array C1 clone intrinsic in PPC
Reviewed-by: mdoerr, amitkumar
This commit is contained in:
parent
a2030fff98
commit
6968770b1e
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2023 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1827,18 +1827,17 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
|
|
||||||
int flags = op->flags();
|
int flags = op->flags();
|
||||||
ciArrayKlass* default_type = op->expected_type();
|
ciArrayKlass* default_type = op->expected_type();
|
||||||
BasicType basic_type = default_type != nullptr ? default_type->element_type()->basic_type() : T_ILLEGAL;
|
BasicType basic_type = (default_type != nullptr) ? default_type->element_type()->basic_type() : T_ILLEGAL;
|
||||||
if (basic_type == T_ARRAY) basic_type = T_OBJECT;
|
if (basic_type == T_ARRAY) basic_type = T_OBJECT;
|
||||||
|
|
||||||
// Set up the arraycopy stub information.
|
// Set up the arraycopy stub information.
|
||||||
ArrayCopyStub* stub = op->stub();
|
ArrayCopyStub* stub = op->stub();
|
||||||
const int frame_resize = frame::native_abi_reg_args_size - sizeof(frame::java_abi); // C calls need larger frame.
|
|
||||||
|
|
||||||
// Always do stub if no type information is available. It's ok if
|
// Always do stub if no type information is available. It's ok if
|
||||||
// the known type isn't loaded since the code sanity checks
|
// the known type isn't loaded since the code sanity checks
|
||||||
// in debug mode and the type isn't required when we know the exact type
|
// in debug mode and the type isn't required when we know the exact type
|
||||||
// also check that the type is an array type.
|
// also check that the type is an array type.
|
||||||
if (op->expected_type() == nullptr) {
|
if (default_type == nullptr) {
|
||||||
assert(src->is_nonvolatile() && src_pos->is_nonvolatile() && dst->is_nonvolatile() && dst_pos->is_nonvolatile() &&
|
assert(src->is_nonvolatile() && src_pos->is_nonvolatile() && dst->is_nonvolatile() && dst_pos->is_nonvolatile() &&
|
||||||
length->is_nonvolatile(), "must preserve");
|
length->is_nonvolatile(), "must preserve");
|
||||||
address copyfunc_addr = StubRoutines::generic_arraycopy();
|
address copyfunc_addr = StubRoutines::generic_arraycopy();
|
||||||
@ -1873,7 +1872,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(default_type != nullptr && default_type->is_array_klass(), "must be true at this point");
|
assert(default_type != nullptr && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point");
|
||||||
Label cont, slow, copyfunc;
|
Label cont, slow, copyfunc;
|
||||||
|
|
||||||
bool simple_check_flag_set = flags & (LIR_OpArrayCopy::src_null_check |
|
bool simple_check_flag_set = flags & (LIR_OpArrayCopy::src_null_check |
|
||||||
@ -1968,7 +1967,11 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
int shift = shift_amount(basic_type);
|
int shift = shift_amount(basic_type);
|
||||||
|
|
||||||
if (!(flags & LIR_OpArrayCopy::type_check)) {
|
if (!(flags & LIR_OpArrayCopy::type_check)) {
|
||||||
__ b(cont);
|
if (stub != nullptr) {
|
||||||
|
__ b(cont);
|
||||||
|
__ bind(slow);
|
||||||
|
__ b(*stub->entry());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// We don't know the array types are compatible.
|
// We don't know the array types are compatible.
|
||||||
if (basic_type != T_OBJECT) {
|
if (basic_type != T_OBJECT) {
|
||||||
@ -2089,9 +2092,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
__ add(dst_pos, tmp, dst_pos);
|
__ add(dst_pos, tmp, dst_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
__ bind(slow);
|
||||||
|
__ b(*stub->entry());
|
||||||
}
|
}
|
||||||
__ bind(slow);
|
|
||||||
__ b(*stub->entry());
|
|
||||||
__ bind(cont);
|
__ bind(cont);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -2104,7 +2107,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
// subtype which we can't check or src is the same array as dst
|
// subtype which we can't check or src is the same array as dst
|
||||||
// but not necessarily exactly of type default_type.
|
// but not necessarily exactly of type default_type.
|
||||||
Label known_ok, halt;
|
Label known_ok, halt;
|
||||||
metadata2reg(op->expected_type()->constant_encoding(), tmp);
|
metadata2reg(default_type->constant_encoding(), tmp);
|
||||||
if (UseCompressedClassPointers) {
|
if (UseCompressedClassPointers) {
|
||||||
// Tmp holds the default type. It currently comes uncompressed after the
|
// Tmp holds the default type. It currently comes uncompressed after the
|
||||||
// load of a constant, so encode it.
|
// load of a constant, so encode it.
|
||||||
@ -2180,7 +2183,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
|||||||
__ mr(len, length);
|
__ mr(len, length);
|
||||||
__ call_c_with_frame_resize(entry, /*stub does not need resized frame*/ 0);
|
__ call_c_with_frame_resize(entry, /*stub does not need resized frame*/ 0);
|
||||||
|
|
||||||
__ bind(*stub->continuation());
|
if (stub != nullptr) {
|
||||||
|
__ bind(*stub->continuation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2301,7 +2306,8 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
|
|||||||
arrayOopDesc::base_offset_in_bytes(op->type()),
|
arrayOopDesc::base_offset_in_bytes(op->type()),
|
||||||
type2aelembytes(op->type()),
|
type2aelembytes(op->type()),
|
||||||
op->klass()->as_register(),
|
op->klass()->as_register(),
|
||||||
*op->stub()->entry());
|
*op->stub()->entry(),
|
||||||
|
op->zero_array());
|
||||||
}
|
}
|
||||||
__ bind(*op->stub()->continuation());
|
__ bind(*op->stub()->continuation());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2023 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -758,7 +758,13 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
|
|||||||
assert(x->number_of_arguments() == 5, "wrong type");
|
assert(x->number_of_arguments() == 5, "wrong type");
|
||||||
|
|
||||||
// Make all state_for calls early since they can emit code.
|
// Make all state_for calls early since they can emit code.
|
||||||
CodeEmitInfo* info = state_for(x, x->state());
|
CodeEmitInfo* info = nullptr;
|
||||||
|
if (x->state_before() != nullptr && x->state_before()->force_reexecute()) {
|
||||||
|
info = state_for(x, x->state_before());
|
||||||
|
info->set_force_reexecute();
|
||||||
|
} else {
|
||||||
|
info = state_for(x, x->state());
|
||||||
|
}
|
||||||
|
|
||||||
LIRItem src (x->argument_at(0), this);
|
LIRItem src (x->argument_at(0), this);
|
||||||
LIRItem src_pos (x->argument_at(1), this);
|
LIRItem src_pos (x->argument_at(1), this);
|
||||||
@ -778,7 +784,9 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
|
|||||||
int flags;
|
int flags;
|
||||||
ciArrayKlass* expected_type;
|
ciArrayKlass* expected_type;
|
||||||
arraycopy_helper(x, &flags, &expected_type);
|
arraycopy_helper(x, &flags, &expected_type);
|
||||||
|
if (x->check_flag(Instruction::OmitChecksFlag)) {
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
__ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(),
|
__ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(),
|
||||||
length.result(), tmp,
|
length.result(), tmp,
|
||||||
expected_type, flags, info);
|
expected_type, flags, info);
|
||||||
@ -903,7 +911,13 @@ void LIRGenerator::do_NewInstance(NewInstance* x) {
|
|||||||
|
|
||||||
void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
|
void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
|
||||||
// Evaluate state_for early since it may emit code.
|
// Evaluate state_for early since it may emit code.
|
||||||
CodeEmitInfo* info = state_for(x, x->state());
|
CodeEmitInfo* info = nullptr;
|
||||||
|
if (x->state_before() != nullptr && x->state_before()->force_reexecute()) {
|
||||||
|
info = state_for(x, x->state_before());
|
||||||
|
info->set_force_reexecute();
|
||||||
|
} else {
|
||||||
|
info = state_for(x, x->state());
|
||||||
|
}
|
||||||
|
|
||||||
LIRItem length(x->length(), this);
|
LIRItem length(x->length(), this);
|
||||||
length.load_item();
|
length.load_item();
|
||||||
@ -921,7 +935,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
|
|||||||
__ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg);
|
__ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg);
|
||||||
|
|
||||||
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
||||||
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
|
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path, x->zero_array());
|
||||||
|
|
||||||
// Must prevent reordering of stores for object initialization
|
// Must prevent reordering of stores for object initialization
|
||||||
// with stores that publish the new object.
|
// with stores that publish the new object.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -310,7 +310,8 @@ void C1_MacroAssembler::allocate_array(
|
|||||||
int base_offset_in_bytes, // elements offset in bytes
|
int base_offset_in_bytes, // elements offset in bytes
|
||||||
int elt_size, // element size in bytes
|
int elt_size, // element size in bytes
|
||||||
Register klass, // object klass
|
Register klass, // object klass
|
||||||
Label& slow_case // continuation point if fast allocation fails
|
Label& slow_case, // continuation point if fast allocation fails
|
||||||
|
bool zero_array // zero the allocated array or not
|
||||||
) {
|
) {
|
||||||
assert_different_registers(obj, len, t1, t2, t3, klass);
|
assert_different_registers(obj, len, t1, t2, t3, klass);
|
||||||
|
|
||||||
@ -346,23 +347,25 @@ void C1_MacroAssembler::allocate_array(
|
|||||||
try_allocate(obj, arr_size, 0, t2, t3, slow_case);
|
try_allocate(obj, arr_size, 0, t2, t3, slow_case);
|
||||||
initialize_header(obj, klass, len, t2, t3);
|
initialize_header(obj, klass, len, t2, t3);
|
||||||
|
|
||||||
// Initialize body.
|
if (zero_array) {
|
||||||
const Register base = t2;
|
// Initialize body.
|
||||||
const Register index = t3;
|
const Register base = t2;
|
||||||
addi(base, obj, base_offset_in_bytes); // compute address of first element
|
const Register index = t3;
|
||||||
addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear
|
addi(base, obj, base_offset_in_bytes); // compute address of first element
|
||||||
|
addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear
|
||||||
|
|
||||||
// Zero first 4 bytes, if start offset is not word aligned.
|
// Zero first 4 bytes, if start offset is not word aligned.
|
||||||
if (!is_aligned(base_offset_in_bytes, BytesPerWord)) {
|
if (!is_aligned(base_offset_in_bytes, BytesPerWord)) {
|
||||||
assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned");
|
assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned");
|
||||||
li(t1, 0);
|
li(t1, 0);
|
||||||
stw(t1, 0, base);
|
stw(t1, 0, base);
|
||||||
addi(base, base, BytesPerInt);
|
addi(base, base, BytesPerInt);
|
||||||
// Note: initialize_body will align index down, no need to correct it here.
|
// Note: initialize_body will align index down, no need to correct it here.
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize_body(base, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize_body(base, index);
|
|
||||||
|
|
||||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
//assert(obj == O0, "must be");
|
//assert(obj == O0, "must be");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -83,7 +83,8 @@
|
|||||||
int base_offset_in_bytes, // elements offset in bytes
|
int base_offset_in_bytes, // elements offset in bytes
|
||||||
int elt_size, // element size in bytes
|
int elt_size, // element size in bytes
|
||||||
Register klass, // object klass
|
Register klass, // object klass
|
||||||
Label& slow_case // continuation point if fast allocation fails
|
Label& slow_case, // continuation point if fast allocation fails
|
||||||
|
bool zero_array // zero the allocated array or not
|
||||||
);
|
);
|
||||||
|
|
||||||
void null_check(Register r, Label *Lnull = nullptr);
|
void null_check(Register r, Label *Lnull = nullptr);
|
||||||
|
@ -235,7 +235,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
|
|||||||
case vmIntrinsics::_counterTime:
|
case vmIntrinsics::_counterTime:
|
||||||
#endif
|
#endif
|
||||||
case vmIntrinsics::_getObjectSize:
|
case vmIntrinsics::_getObjectSize:
|
||||||
#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV)
|
#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64)
|
||||||
case vmIntrinsics::_clone:
|
case vmIntrinsics::_clone:
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
@ -351,7 +351,7 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_
|
|||||||
, _tmp(tmp)
|
, _tmp(tmp)
|
||||||
, _expected_type(expected_type)
|
, _expected_type(expected_type)
|
||||||
, _flags(flags) {
|
, _flags(flags) {
|
||||||
#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV)
|
#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64)
|
||||||
if (expected_type != nullptr && flags == 0) {
|
if (expected_type != nullptr && flags == 0) {
|
||||||
_stub = nullptr;
|
_stub = nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user