8331935: Add support for primitive array C1 clone intrinsic in PPC

Reviewed-by: mdoerr, amitkumar
This commit is contained in:
Varada M 2024-06-07 08:24:15 +00:00 committed by Amit Kumar
parent a2030fff98
commit 6968770b1e
6 changed files with 60 additions and 36 deletions

View File

@ -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());
} }

View File

@ -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.

View File

@ -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");

View File

@ -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);

View File

@ -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;

View File

@ -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 {