From 6968770b1e918c74fc009e3562a827bb4acbe2d7 Mon Sep 17 00:00:00 2001 From: Varada M Date: Fri, 7 Jun 2024 08:24:15 +0000 Subject: [PATCH] 8331935: Add support for primitive array C1 clone intrinsic in PPC Reviewed-by: mdoerr, amitkumar --- src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp | 28 +++++++++------ src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp | 24 ++++++++++--- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 35 ++++++++++--------- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp | 5 +-- src/hotspot/share/c1/c1_Compiler.cpp | 2 +- src/hotspot/share/c1/c1_LIR.cpp | 2 +- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 3ae35949b21..0c1e23c6353 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * 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. * * 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(); 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; // Set up the arraycopy stub information. 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 // 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 // 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() && length->is_nonvolatile(), "must preserve"); address copyfunc_addr = StubRoutines::generic_arraycopy(); @@ -1873,7 +1872,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { 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; 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); if (!(flags & LIR_OpArrayCopy::type_check)) { - __ b(cont); + if (stub != nullptr) { + __ b(cont); + __ bind(slow); + __ b(*stub->entry()); + } } else { // We don't know the array types are compatible. if (basic_type != T_OBJECT) { @@ -2089,9 +2092,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ add(dst_pos, tmp, dst_pos); } } + __ bind(slow); + __ b(*stub->entry()); } - __ bind(slow); - __ b(*stub->entry()); __ bind(cont); #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 // but not necessarily exactly of type default_type. Label known_ok, halt; - metadata2reg(op->expected_type()->constant_encoding(), tmp); + metadata2reg(default_type->constant_encoding(), tmp); if (UseCompressedClassPointers) { // Tmp holds the default type. It currently comes uncompressed after the // load of a constant, so encode it. @@ -2180,7 +2183,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ mr(len, length); __ 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()), type2aelembytes(op->type()), op->klass()->as_register(), - *op->stub()->entry()); + *op->stub()->entry(), + op->zero_array()); } __ bind(*op->stub()->continuation()); } diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index 2caca1dc556..04762a22c61 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * 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. * * 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"); // 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_pos (x->argument_at(1), this); @@ -778,7 +784,9 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { int flags; ciArrayKlass* 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(), length.result(), tmp, expected_type, flags, info); @@ -903,7 +911,13 @@ void LIRGenerator::do_NewInstance(NewInstance* x) { void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { // 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); length.load_item(); @@ -921,7 +935,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { __ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); 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 // with stores that publish the new object. diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 9da5a2c6580..abc439df827 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * 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. * * 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 elt_size, // element size in bytes 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); @@ -346,23 +347,25 @@ void C1_MacroAssembler::allocate_array( try_allocate(obj, arr_size, 0, t2, t3, slow_case); initialize_header(obj, klass, len, t2, t3); - // Initialize body. - const Register base = t2; - const Register index = t3; - 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 + if (zero_array) { + // Initialize body. + const Register base = t2; + const Register index = t3; + 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. - if (!is_aligned(base_offset_in_bytes, BytesPerWord)) { - assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned"); - li(t1, 0); - stw(t1, 0, base); - addi(base, base, BytesPerInt); - // Note: initialize_body will align index down, no need to correct it here. + // Zero first 4 bytes, if start offset is not word aligned. + if (!is_aligned(base_offset_in_bytes, BytesPerWord)) { + assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned"); + li(t1, 0); + stw(t1, 0, base); + addi(base, base, BytesPerInt); + // 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()) { Unimplemented(); //assert(obj == O0, "must be"); diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp index ab31431e67d..c0a3dd3b83c 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* * 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. * * 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 elt_size, // element size in bytes 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); diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index 897e2b6470d..e1c4e90d063 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -235,7 +235,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_counterTime: #endif 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: #endif break; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index 6ca5b1bd136..3f53011024b 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -351,7 +351,7 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_ , _tmp(tmp) , _expected_type(expected_type) , _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) { _stub = nullptr; } else {