diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 9c9a9d17ac4..7b2dd16b00e 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -146,8 +146,6 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // r19_sender_sp: sender sp // esp: args - if (!InlineIntrinsics) return NULL; // Generate a vanilla entry - // These don't need a safepoint check because they aren't virtually // callable. We won't enter these intrinsics from compiled code. // If in the future we added an intrinsic which was virtually callable @@ -301,12 +299,7 @@ void TemplateInterpreterGenerator::generate_transcendental_entry(AbstractInterpr } address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16)) { - return nullptr; - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); // r19_sender_sp: sender sp // stack: // [ arg ] <-- esp @@ -323,12 +316,7 @@ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { } address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16)) { - return nullptr; - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); // r19_sender_sp: sender sp // stack: // [ arg ] <-- esp @@ -963,48 +951,46 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { * int java.util.zip.CRC32.update(int crc, int b) */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rmethod: Method* - // r19_sender_sp: senderSP must preserved for slow path - // esp: args + // rmethod: Method* + // r19_sender_sp: senderSP must preserved for slow path + // esp: args - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); + Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = c_rarg0; // crc - const Register val = c_rarg1; // source java byte value - const Register tbl = c_rarg2; // scratch + // Load parameters + const Register crc = c_rarg0; // crc + const Register val = c_rarg1; // source java byte value + const Register tbl = c_rarg2; // scratch - // Arguments are reversed on java expression stack - __ ldrw(val, Address(esp, 0)); // byte value - __ ldrw(crc, Address(esp, wordSize)); // Initial CRC + // Arguments are reversed on java expression stack + __ ldrw(val, Address(esp, 0)); // byte value + __ ldrw(crc, Address(esp, wordSize)); // Initial CRC - uint64_t offset; - __ adrp(tbl, ExternalAddress(StubRoutines::crc_table_addr()), offset); - __ add(tbl, tbl, offset); + uint64_t offset; + __ adrp(tbl, ExternalAddress(StubRoutines::crc_table_addr()), offset); + __ add(tbl, tbl, offset); - __ mvnw(crc, crc); // ~crc - __ update_byte_crc32(crc, val, tbl); - __ mvnw(crc, crc); // ~crc + __ mvnw(crc, crc); // ~crc + __ update_byte_crc32(crc, val, tbl); + __ mvnw(crc, crc); // ~crc - // result in c_rarg0 + // result in c_rarg0 - __ andr(sp, r19_sender_sp, -16); - __ ret(lr); + __ andr(sp, r19_sender_sp, -16); + __ ret(lr); - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; - } - return NULL; + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -1013,53 +999,51 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rmethod,: Method* - // r19_sender_sp: senderSP must preserved for slow path + // rmethod,: Method* + // r19_sender_sp: senderSP must preserved for slow path - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); + Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = c_rarg0; // crc - const Register buf = c_rarg1; // source java byte array address - const Register len = c_rarg2; // length - const Register off = len; // offset (never overlaps with 'len') + // Load parameters + const Register crc = c_rarg0; // crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; // length + const Register off = len; // offset (never overlaps with 'len') - // Arguments are reversed on java expression stack - // Calculate address of start element - if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { - __ ldr(buf, Address(esp, 2*wordSize)); // long buf - __ ldrw(off, Address(esp, wordSize)); // offset - __ add(buf, buf, off); // + offset - __ ldrw(crc, Address(esp, 4*wordSize)); // Initial CRC - } else { - __ ldr(buf, Address(esp, 2*wordSize)); // byte[] array - __ add(buf, buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ ldrw(off, Address(esp, wordSize)); // offset - __ add(buf, buf, off); // + offset - __ ldrw(crc, Address(esp, 3*wordSize)); // Initial CRC - } - // Can now load 'len' since we're finished with 'off' - __ ldrw(len, Address(esp, 0x0)); // Length - - __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP - - // We are frameless so we can just jump to the stub. - __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32())); - - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; + // Arguments are reversed on java expression stack + // Calculate address of start element + if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { + __ ldr(buf, Address(esp, 2*wordSize)); // long buf + __ ldrw(off, Address(esp, wordSize)); // offset + __ add(buf, buf, off); // + offset + __ ldrw(crc, Address(esp, 4*wordSize)); // Initial CRC + } else { + __ ldr(buf, Address(esp, 2*wordSize)); // byte[] array + __ add(buf, buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ ldrw(off, Address(esp, wordSize)); // offset + __ add(buf, buf, off); // + offset + __ ldrw(crc, Address(esp, 3*wordSize)); // Initial CRC } - return NULL; + // Can now load 'len' since we're finished with 'off' + __ ldrw(len, Address(esp, 0x0)); // Length + + __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP + + // We are frameless so we can just jump to the stub. + __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32())); + + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -1070,37 +1054,35 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI * CRC32C also uses an "end" variable instead of the length variable CRC32 uses */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32CIntrinsics) { - address entry = __ pc(); + assert(UseCRC32CIntrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // Prepare jump to stub using parameters from the stack - const Register crc = c_rarg0; // initial crc - const Register buf = c_rarg1; // source java byte array address - const Register len = c_rarg2; // len argument to the kernel + // Prepare jump to stub using parameters from the stack + const Register crc = c_rarg0; // initial crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; // len argument to the kernel - const Register end = len; // index of last element to process - const Register off = crc; // offset + const Register end = len; // index of last element to process + const Register off = crc; // offset - __ ldrw(end, Address(esp)); // int end - __ ldrw(off, Address(esp, wordSize)); // int offset - __ sub(len, end, off); - __ ldr(buf, Address(esp, 2*wordSize)); // byte[] buf | long buf - __ add(buf, buf, off); // + offset - if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { - __ ldrw(crc, Address(esp, 4*wordSize)); // long crc - } else { - __ add(buf, buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ ldrw(crc, Address(esp, 3*wordSize)); // long crc - } - - __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP - - // Jump to the stub. - __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C())); - - return entry; + __ ldrw(end, Address(esp)); // int end + __ ldrw(off, Address(esp, wordSize)); // int offset + __ sub(len, end, off); + __ ldr(buf, Address(esp, 2*wordSize)); // byte[] buf | long buf + __ add(buf, buf, off); // + offset + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { + __ ldrw(crc, Address(esp, 4*wordSize)); // long crc + } else { + __ add(buf, buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ ldrw(crc, Address(esp, 3*wordSize)); // long crc } - return NULL; + + __ andr(sp, r19_sender_sp, -16); // Restore the caller's SP + + // Jump to the stub. + __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C())); + + return entry; } void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { @@ -1742,6 +1724,11 @@ address TemplateInterpreterGenerator::generate_currentThread() { return entry_point; } +// Not supported +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } //----------------------------------------------------------------------------- // Exceptions diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index 5542cc96532..36c3de48668 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -122,8 +122,6 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { } address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { - if (!InlineIntrinsics) return nullptr; // Generate a vanilla entry - address entry_point = nullptr; Register continuation = LR; bool use_runtime_call = false; @@ -780,9 +778,14 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { } // Not supported +address TemplateInterpreterGenerator::generate_currentThread() { return nullptr; } address TemplateInterpreterGenerator::generate_CRC32_update_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return nullptr; } address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { return nullptr; } diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index 22488a3d23f..8f425c1ac37 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -1746,52 +1746,49 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { * int java.util.zip.CRC32.update(int crc, int b) */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { - if (UseCRC32Intrinsics) { - address start = __ pc(); // Remember stub start address (is rtn value). - Label slow_path; + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address start = __ pc(); // Remember stub start address (is rtn value). + Label slow_path; - // Safepoint check - const Register sync_state = R11_scratch1; - __ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */); + // Safepoint check + const Register sync_state = R11_scratch1; + __ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we not even call stub code (we generate the code inline) - // and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. - // Load java parameters. - // R15_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = R15_esp; - const Register crc = R3_ARG1; // crc value - const Register data = R4_ARG2; - const Register table = R5_ARG3; // address of crc32 table + // Load java parameters. + // R15_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; + const Register table = R5_ARG3; // address of crc32 table - BLOCK_COMMENT("CRC32_update {"); + BLOCK_COMMENT("CRC32_update {"); - // Arguments are reversed on java expression stack + // Arguments are reversed on java expression stack #ifdef VM_LITTLE_ENDIAN - int data_offs = 0+1*wordSize; // (stack) address of byte value. Emitter expects address, not value. - // Being passed as an int, the single byte is at offset +0. + int data_offs = 0+1*wordSize; // (stack) address of byte value. Emitter expects address, not value. + // Being passed as an int, the single byte is at offset +0. #else - int data_offs = 3+1*wordSize; // (stack) address of byte value. Emitter expects address, not value. - // Being passed from java as an int, the single byte is at offset +3. + int data_offs = 3+1*wordSize; // (stack) address of byte value. Emitter expects address, not value. + // Being passed from java as an int, the single byte is at offset +3. #endif - __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. - __ lbz(data, data_offs, argP); // Byte from buffer, zero-extended. - __ load_const_optimized(table, StubRoutines::crc_table_addr(), R0); - __ kernel_crc32_singleByteReg(crc, data, table, true); + __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. + __ lbz(data, data_offs, argP); // Byte from buffer, zero-extended. + __ load_const_optimized(table, StubRoutines::crc_table_addr(), R0); + __ kernel_crc32_singleByteReg(crc, data, table, true); - // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). - __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); - __ blr(); + // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). + __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); + __ blr(); - // Generate a vanilla native entry as the slow path. - BLOCK_COMMENT("} CRC32_update"); - BIND(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1); - return start; - } - - return NULL; + // Generate a vanilla native entry as the slow path. + BLOCK_COMMENT("} CRC32_update"); + BIND(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1); + return start; } /** @@ -1800,69 +1797,66 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long* buf, int off, int len) */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32Intrinsics) { - address start = __ pc(); // Remember stub start address (is rtn value). - Label slow_path; + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address start = __ pc(); // Remember stub start address (is rtn value). + Label slow_path; - // Safepoint check - const Register sync_state = R11_scratch1; - __ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */); + // Safepoint check + const Register sync_state = R11_scratch1; + __ safepoint_poll(slow_path, sync_state, false /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we not even call stub code (we generate the code inline) - // and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. - // Load parameters. - // Z_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = R15_esp; - const Register crc = R3_ARG1; // crc value - const Register data = R4_ARG2; // address of java byte array - const Register dataLen = R5_ARG3; // source data len - const Register tmp = R11_scratch1; + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; // address of java byte array + const Register dataLen = R5_ARG3; // source data len + const Register tmp = R11_scratch1; - // Arguments are reversed on java expression stack. - // Calculate address of start element. - if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { // Used for "updateByteBuffer direct". - BLOCK_COMMENT("CRC32_updateByteBuffer {"); - // crc @ (SP + 5W) (32bit) - // buf @ (SP + 3W) (64bit ptr to long array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off - __ ld( data, 3*wordSize, argP); // start of byte buffer - __ lwa( tmp, 2*wordSize, argP); // byte buffer offset - __ lwa( dataLen, 1*wordSize, argP); // #bytes to process - __ lwz( crc, 5*wordSize, argP); // current crc state - __ add( data, data, tmp); // Add byte buffer offset. - } else { // Used for "updateBytes update". - BLOCK_COMMENT("CRC32_updateBytes {"); - // crc @ (SP + 4W) (32bit) - // buf @ (SP + 3W) (64bit ptr to byte array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off + base_offset - __ ld( data, 3*wordSize, argP); // start of byte buffer - __ lwa( tmp, 2*wordSize, argP); // byte buffer offset - __ lwa( dataLen, 1*wordSize, argP); // #bytes to process - __ add( data, data, tmp); // add byte buffer offset - __ lwz( crc, 4*wordSize, argP); // current crc state - __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - } - - __ crc32(crc, data, dataLen, R2, R6, R7, R8, R9, R10, R11, R12, false); - - // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). - __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); - __ blr(); - - // Generate a vanilla native entry as the slow path. - BLOCK_COMMENT("} CRC32_updateBytes(Buffer)"); - BIND(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1); - return start; + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { // Used for "updateByteBuffer direct". + BLOCK_COMMENT("CRC32_updateByteBuffer {"); + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ lwz( crc, 5*wordSize, argP); // current crc state + __ add( data, data, tmp); // Add byte buffer offset. + } else { // Used for "updateBytes update". + BLOCK_COMMENT("CRC32_updateBytes {"); + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ add( data, data, tmp); // add byte buffer offset + __ lwz( crc, 4*wordSize, argP); // current crc state + __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } - return NULL; + __ crc32(crc, data, dataLen, R2, R6, R7, R8, R9, R10, R11, R12, false); + + // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). + __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); + __ blr(); + + // Generate a vanilla native entry as the slow path. + BLOCK_COMMENT("} CRC32_updateBytes(Buffer)"); + BIND(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1); + return start; } @@ -1874,66 +1868,68 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI * CRC32C also uses an "end" variable instead of the length variable CRC32 uses **/ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32CIntrinsics) { - address start = __ pc(); // Remember stub start address (is rtn value). + assert(UseCRC32CIntrinsics, "this intrinsic is not supported"); + address start = __ pc(); // Remember stub start address (is rtn value). - // We don't generate local frame and don't align stack because - // we not even call stub code (we generate the code inline) - // and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. - // Load parameters. - // Z_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = R15_esp; - const Register crc = R3_ARG1; // crc value - const Register data = R4_ARG2; // address of java byte array - const Register dataLen = R5_ARG3; // source data len - const Register tmp = R11_scratch1; + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; // address of java byte array + const Register dataLen = R5_ARG3; // source data len + const Register tmp = R11_scratch1; - // Arguments are reversed on java expression stack. - // Calculate address of start element. - if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer". - BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); - // crc @ (SP + 5W) (32bit) - // buf @ (SP + 3W) (64bit ptr to long array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off - __ ld( data, 3*wordSize, argP); // start of byte buffer - __ lwa( tmp, 2*wordSize, argP); // byte buffer offset - __ lwa( dataLen, 1*wordSize, argP); // #bytes to process - __ lwz( crc, 5*wordSize, argP); // current crc state - __ add( data, data, tmp); // Add byte buffer offset. - __ sub( dataLen, dataLen, tmp); // (end_index - offset) - } else { // Used for "updateBytes update". - BLOCK_COMMENT("CRC32C_updateBytes {"); - // crc @ (SP + 4W) (32bit) - // buf @ (SP + 3W) (64bit ptr to byte array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off + base_offset - __ ld( data, 3*wordSize, argP); // start of byte buffer - __ lwa( tmp, 2*wordSize, argP); // byte buffer offset - __ lwa( dataLen, 1*wordSize, argP); // #bytes to process - __ add( data, data, tmp); // add byte buffer offset - __ sub( dataLen, dataLen, tmp); // (end_index - offset) - __ lwz( crc, 4*wordSize, argP); // current crc state - __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - } - - __ crc32(crc, data, dataLen, R2, R6, R7, R8, R9, R10, R11, R12, true); - - // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). - __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); - __ blr(); - - BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); - return start; + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer". + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ lwz( crc, 5*wordSize, argP); // current crc state + __ add( data, data, tmp); // Add byte buffer offset. + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + } else { // Used for "updateBytes update". + BLOCK_COMMENT("CRC32C_updateBytes {"); + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ add( data, data, tmp); // add byte buffer offset + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + __ lwz( crc, 4*wordSize, argP); // current crc state + __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } - return NULL; + __ crc32(crc, data, dataLen, R2, R6, R7, R8, R9, R10, R11, R12, true); + + // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). + __ resize_frame_absolute(R21_sender_SP, R11_scratch1, R0); + __ blr(); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return start; } // Not supported +address TemplateInterpreterGenerator::generate_currentThread() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { return nullptr; } diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 4ed383fdf5a..9e24cee7cb8 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -143,10 +143,6 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // x19_sender_sp: sender sp // esp: args - if (!InlineIntrinsics) { - return NULL; // Generate a vanilla entry - } - // These don't need a safepoint check because they aren't virtually // callable. We won't enter these intrinsics from compiled code. // If in the future we added an intrinsic which was virtually callable @@ -301,10 +297,6 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M return entry_point; } -// Not supported -address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { return nullptr; } -address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { return nullptr; } - // Abstract method entry // Attempt to execute abstract method. Throw exception address TemplateInterpreterGenerator::generate_abstract_entry(void) { @@ -864,7 +856,7 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { // TODO: Unimplemented generate_CRC32_update_entry - return 0; + return nullptr; } /** @@ -874,7 +866,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { // TODO: Unimplemented generate_CRC32_updateBytes_entry - return 0; + return nullptr; } /** @@ -886,9 +878,17 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { // TODO: Unimplemented generate_CRC32C_updateBytes_entry - return 0; + return nullptr; } +// Not supported +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { return nullptr; } + void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { // See more discussion in stackOverflow.hpp. diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index bd6145941a2..996ef31dba8 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -1801,50 +1801,46 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { * int java.util.zip.CRC32.update(int crc, int b) */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + uint64_t entry_off = __ offset(); + Label slow_path; - if (UseCRC32Intrinsics) { - uint64_t entry_off = __ offset(); - Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ safepoint_poll(slow_path, Z_R1); - // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, Z_R1); + BLOCK_COMMENT("CRC32_update {"); - BLOCK_COMMENT("CRC32_update {"); + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. - // We don't generate local frame and don't align stack because - // we not even call stub code (we generate the code inline) - // and there is no safepoint on this path. + // Load java parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte value (kernel_crc32 needs address) + const Register dataLen = Z_ARG3; // source data len (1 byte). Not used because calling the single-byte emitter. + const Register table = Z_ARG4; // address of crc32 table - // Load java parameters. - // Z_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = Z_esp; - const Register crc = Z_ARG1; // crc value - const Register data = Z_ARG2; // address of java byte value (kernel_crc32 needs address) - const Register dataLen = Z_ARG3; // source data len (1 byte). Not used because calling the single-byte emitter. - const Register table = Z_ARG4; // address of crc32 table - - // Arguments are reversed on java expression stack. - __ z_la(data, 3+1*wordSize, argP); // byte value (stack address). + // Arguments are reversed on java expression stack. + __ z_la(data, 3+1*wordSize, argP); // byte value (stack address). // Being passed as an int, the single byte is at offset +3. - __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. + __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. - StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true); + StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); + __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true); - // Restore caller sp for c2i case. - __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. - __ z_br(Z_R14); + __ z_br(Z_R14); - BLOCK_COMMENT("} CRC32_update"); + BLOCK_COMMENT("} CRC32_update"); - // Use a previously generated vanilla native entry as the slow path. - BIND(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), Z_R1); - return __ addr_at(entry_off); - } - - return NULL; + // Use a previously generated vanilla native entry as the slow path. + BIND(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), Z_R1); + return __ addr_at(entry_off); } @@ -1854,77 +1850,73 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long* buf, int off, int len) */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + uint64_t entry_off = __ offset(); + Label slow_path; - if (UseCRC32Intrinsics) { - uint64_t entry_off = __ offset(); - Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ safepoint_poll(slow_path, Z_R1); - // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, Z_R1); + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte array + const Register dataLen = Z_ARG3; // source data len + const Register table = Z_ARG4; // address of crc32 table + const Register t0 = Z_R10; // work reg for kernel* emitters + const Register t1 = Z_R11; // work reg for kernel* emitters + const Register t2 = Z_R12; // work reg for kernel* emitters + const Register t3 = Z_R13; // work reg for kernel* emitters - // Load parameters. - // Z_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = Z_esp; - const Register crc = Z_ARG1; // crc value - const Register data = Z_ARG2; // address of java byte array - const Register dataLen = Z_ARG3; // source data len - const Register table = Z_ARG4; // address of crc32 table - const Register t0 = Z_R10; // work reg for kernel* emitters - const Register t1 = Z_R11; // work reg for kernel* emitters - const Register t2 = Z_R12; // work reg for kernel* emitters - const Register t3 = Z_R13; // work reg for kernel* emitters - - // Arguments are reversed on java expression stack. - // Calculate address of start element. - if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { // Used for "updateByteBuffer direct". - // crc @ (SP + 5W) (32bit) - // buf @ (SP + 3W) (64bit ptr to long array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off - BLOCK_COMMENT("CRC32_updateByteBuffer {"); - __ z_llgf(crc, 5*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer - __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. - __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process - } else { // Used for "updateBytes update". - // crc @ (SP + 4W) (32bit) - // buf @ (SP + 3W) (64bit ptr to byte array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off + base_offset - BLOCK_COMMENT("CRC32_updateBytes {"); - __ z_llgf(crc, 4*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer - __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. - __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process - __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - } - - StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - - __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. - __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true); - __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. - - // Restore caller sp for c2i case. - __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. - - __ z_br(Z_R14); - - BLOCK_COMMENT("} CRC32_update{Bytes|ByteBuffer}"); - - // Use a previously generated vanilla native entry as the slow path. - BIND(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), Z_R1); - return __ addr_at(entry_off); + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { // Used for "updateByteBuffer direct". + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + BLOCK_COMMENT("CRC32_updateByteBuffer {"); + __ z_llgf(crc, 5*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process + } else { // Used for "updateBytes update". + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + BLOCK_COMMENT("CRC32_updateBytes {"); + __ z_llgf(crc, 4*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process + __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } - return NULL; + StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); + + __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. + __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true); + __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + + __ z_br(Z_R14); + + BLOCK_COMMENT("} CRC32_update{Bytes|ByteBuffer}"); + + // Use a previously generated vanilla native entry as the slow path. + BIND(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), Z_R1); + return __ addr_at(entry_off); } @@ -1936,74 +1928,75 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI * CRC32C also uses an "end" variable instead of the length variable CRC32 uses */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + assert(UseCRC32CIntrinsics, "this intrinsic is not supported"); + uint64_t entry_off = __ offset(); - if (UseCRC32CIntrinsics) { - uint64_t entry_off = __ offset(); + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte array + const Register dataLen = Z_ARG3; // source data len + const Register table = Z_ARG4; // address of crc32 table + const Register t0 = Z_R10; // work reg for kernel* emitters + const Register t1 = Z_R11; // work reg for kernel* emitters + const Register t2 = Z_R12; // work reg for kernel* emitters + const Register t3 = Z_R13; // work reg for kernel* emitters - // Load parameters. - // Z_esp is callers operand stack pointer, i.e. it points to the parameters. - const Register argP = Z_esp; - const Register crc = Z_ARG1; // crc value - const Register data = Z_ARG2; // address of java byte array - const Register dataLen = Z_ARG3; // source data len - const Register table = Z_ARG4; // address of crc32 table - const Register t0 = Z_R10; // work reg for kernel* emitters - const Register t1 = Z_R11; // work reg for kernel* emitters - const Register t2 = Z_R12; // work reg for kernel* emitters - const Register t3 = Z_R13; // work reg for kernel* emitters - - // Arguments are reversed on java expression stack. - // Calculate address of start element. - if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct". - // crc @ (SP + 5W) (32bit) - // buf @ (SP + 3W) (64bit ptr to long array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off - BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); - __ z_llgf(crc, 5*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer - __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. - __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as - __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) - } else { // Used for "updateBytes update". - // crc @ (SP + 4W) (32bit) - // buf @ (SP + 3W) (64bit ptr to byte array) - // off @ (SP + 2W) (32bit) - // dataLen @ (SP + 1W) (32bit) - // data = buf + off + base_offset - BLOCK_COMMENT("CRC32C_updateBytes {"); - __ z_llgf(crc, 4*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer - __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. - __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as - __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) - __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - } - - StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); - - __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. - __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false); - __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. - - // Restore caller sp for c2i case. - __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. - - __ z_br(Z_R14); - - BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); - return __ addr_at(entry_off); + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct". + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + __ z_llgf(crc, 5*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + } else { // Used for "updateBytes update". + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + BLOCK_COMMENT("CRC32C_updateBytes {"); + __ z_llgf(crc, 4*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } - return NULL; + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. + __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false); + __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + + __ z_br(Z_R14); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return __ addr_at(entry_off); } // Not supported +address TemplateInterpreterGenerator::generate_currentThread() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { return nullptr; } address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { return nullptr; } diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp index 50b3d1f707e..bbdc380e265 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp @@ -53,48 +53,46 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { * int java.util.zip.CRC32.update(int crc, int b) */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rbx: Method* - // rsi: senderSP must preserved for slow path, set SP to it on fast path - // rdx: scratch - // rdi: scratch + // rbx: Method* + // rsi: senderSP must preserved for slow path, set SP to it on fast path + // rdx: scratch + // rdi: scratch - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ get_thread(rdi); - __ safepoint_poll(slow_path, rdi, false /* at_return */, false /* in_nmethod */); + Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ get_thread(rdi); + __ safepoint_poll(slow_path, rdi, false /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = rax; // crc - const Register val = rdx; // source java byte value - const Register tbl = rdi; // scratch + // Load parameters + const Register crc = rax; // crc + const Register val = rdx; // source java byte value + const Register tbl = rdi; // scratch - // Arguments are reversed on java expression stack - __ movl(val, Address(rsp, wordSize)); // byte value - __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC + // Arguments are reversed on java expression stack + __ movl(val, Address(rsp, wordSize)); // byte value + __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC - __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr())); - __ notl(crc); // ~crc - __ update_byte_crc32(crc, val, tbl); - __ notl(crc); // ~crc - // result in rax + __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr())); + __ notl(crc); // ~crc + __ update_byte_crc32(crc, val, tbl); + __ notl(crc); // ~crc + // result in rax - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, rsi); // set sp to sender sp - __ jmp(rdi); + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, rsi); // set sp to sender sp + __ jmp(rdi); - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; - } - return NULL; + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -103,62 +101,60 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rbx,: Method* - // rsi: senderSP must preserved for slow path, set SP to it on fast path - // rdx: scratch - // rdi: scratch + // rbx,: Method* + // rsi: senderSP must preserved for slow path, set SP to it on fast path + // rdx: scratch + // rdi: scratch - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ get_thread(rdi); - __ safepoint_poll(slow_path, rdi, false /* at_return */, false /* in_nmethod */); + Label slow_path; + // If we need a safepoint check, generate full interpreter entry. + __ get_thread(rdi); + __ safepoint_poll(slow_path, rdi, false /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = rax; // crc - const Register buf = rdx; // source java byte array address - const Register len = rdi; // length + // Load parameters + const Register crc = rax; // crc + const Register buf = rdx; // source java byte array address + const Register len = rdi; // length - // value x86_32 - // interp. arg ptr ESP + 4 - // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len) - // 3 2 1 0 - // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) - // 4 2,3 1 0 + // value x86_32 + // interp. arg ptr ESP + 4 + // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len) + // 3 2 1 0 + // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) + // 4 2,3 1 0 - // Arguments are reversed on java expression stack - __ movl(len, Address(rsp, 4 + 0)); // Length - // Calculate address of start element - if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { - __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf - __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset - __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC - } else { - __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array - __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset - __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC - } - - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len); - // result in rax - - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, rsi); // set sp to sender sp - __ jmp(rdi); - - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; + // Arguments are reversed on java expression stack + __ movl(len, Address(rsp, 4 + 0)); // Length + // Calculate address of start element + if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { + __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf + __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset + __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC + } else { + __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array + __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset + __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC } - return NULL; + + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len); + // result in rax + + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, rsi); // set sp to sender sp + __ jmp(rdi); + + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -167,45 +163,43 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end) */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32CIntrinsics) { - address entry = __ pc(); - // Load parameters - const Register crc = rax; // crc - const Register buf = rcx; // source java byte array address - const Register len = rdx; // length - const Register end = len; + assert(UseCRC32CIntrinsics, "this intrinsic is not supported"); + address entry = __ pc(); + // Load parameters + const Register crc = rax; // crc + const Register buf = rcx; // source java byte array address + const Register len = rdx; // length + const Register end = len; - // value x86_32 - // interp. arg ptr ESP + 4 - // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end) - // 3 2 1 0 - // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end) - // 4 2,3 1 0 + // value x86_32 + // interp. arg ptr ESP + 4 + // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end) + // 3 2 1 0 + // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end) + // 4 2,3 1 0 - // Arguments are reversed on java expression stack - __ movl(end, Address(rsp, 4 + 0)); // end - __ subl(len, Address(rsp, 4 + 1 * wordSize)); // end - offset == length - // Calculate address of start element - if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { - __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address - __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset - __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC - } else { - __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array - __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset - __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC - } - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len); - // result in rax - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, rsi); // set sp to sender sp - __ jmp(rdi); - - return entry; + // Arguments are reversed on java expression stack + __ movl(end, Address(rsp, 4 + 0)); // end + __ subl(len, Address(rsp, 4 + 1 * wordSize)); // end - offset == length + // Calculate address of start element + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { + __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address + __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset + __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC + } else { + __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array + __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset + __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC } - return NULL; + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len); + // result in rax + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, rsi); // set sp to sender sp + __ jmp(rdi); + + return entry; } /** @@ -319,12 +313,7 @@ address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry( * java.lang.Float.float16ToFloat(short floatBinary16) */ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16)) { - return nullptr; // Generate a vanilla entry - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); address entry = __ pc(); // rsi: the sender's SP @@ -345,12 +334,7 @@ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { * java.lang.Float.floatToFloat16(float value) */ address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat)) { - return nullptr; // Generate a vanilla entry - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); address entry = __ pc(); // rsi: the sender's SP @@ -372,8 +356,6 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // rcx: scratrch // rsi: sender sp - if (!InlineIntrinsics) return NULL; // Generate a vanilla entry - address entry_point = __ pc(); // These don't need a safepoint check because they aren't virtually @@ -518,3 +500,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M return entry_point; } + +// Not supported +address TemplateInterpreterGenerator::generate_currentThread() { return nullptr; } + diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index d514bf54de8..e288b57c8da 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -182,46 +182,44 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { * int java.util.zip.CRC32.update(int crc, int b) */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rbx,: Method* - // r13: senderSP must preserved for slow path, set SP to it on fast path - // c_rarg0: scratch (rdi on non-Win64, rcx on Win64) - // c_rarg1: scratch (rsi on non-Win64, rdx on Win64) + // rbx,: Method* + // r13: senderSP must preserved for slow path, set SP to it on fast path + // c_rarg0: scratch (rdi on non-Win64, rcx on Win64) + // c_rarg1: scratch (rsi on non-Win64, rdx on Win64) - Label slow_path; - __ safepoint_poll(slow_path, r15_thread, true /* at_return */, false /* in_nmethod */); + Label slow_path; + __ safepoint_poll(slow_path, r15_thread, true /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = rax; // crc - const Register val = c_rarg0; // source java byte value - const Register tbl = c_rarg1; // scratch + // Load parameters + const Register crc = rax; // crc + const Register val = c_rarg0; // source java byte value + const Register tbl = c_rarg1; // scratch - // Arguments are reversed on java expression stack - __ movl(val, Address(rsp, wordSize)); // byte value - __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC + // Arguments are reversed on java expression stack + __ movl(val, Address(rsp, wordSize)); // byte value + __ movl(crc, Address(rsp, 2*wordSize)); // Initial CRC - __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr())); - __ notl(crc); // ~crc - __ update_byte_crc32(crc, val, tbl); - __ notl(crc); // ~crc - // result in rax + __ lea(tbl, ExternalAddress(StubRoutines::crc_table_addr())); + __ notl(crc); // ~crc + __ update_byte_crc32(crc, val, tbl); + __ notl(crc); // ~crc + // result in rax - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, r13); // set sp to sender sp - __ jmp(rdi); + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, r13); // set sp to sender sp + __ jmp(rdi); - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; - } - return NULL; + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -230,55 +228,53 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32Intrinsics) { - address entry = __ pc(); + assert(UseCRC32Intrinsics, "this intrinsic is not supported"); + address entry = __ pc(); - // rbx,: Method* - // r13: senderSP must preserved for slow path, set SP to it on fast path + // rbx,: Method* + // r13: senderSP must preserved for slow path, set SP to it on fast path - Label slow_path; - __ safepoint_poll(slow_path, r15_thread, false /* at_return */, false /* in_nmethod */); + Label slow_path; + __ safepoint_poll(slow_path, r15_thread, false /* at_return */, false /* in_nmethod */); - // We don't generate local frame and don't align stack because - // we call stub code and there is no safepoint on this path. + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. - // Load parameters - const Register crc = c_rarg0; // crc - const Register buf = c_rarg1; // source java byte array address - const Register len = c_rarg2; // length - const Register off = len; // offset (never overlaps with 'len') + // Load parameters + const Register crc = c_rarg0; // crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; // length + const Register off = len; // offset (never overlaps with 'len') - // Arguments are reversed on java expression stack - // Calculate address of start element - if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { - __ movptr(buf, Address(rsp, 3*wordSize)); // long buf - __ movl2ptr(off, Address(rsp, 2*wordSize)); // offset - __ addq(buf, off); // + offset - __ movl(crc, Address(rsp, 5*wordSize)); // Initial CRC - } else { - __ movptr(buf, Address(rsp, 3*wordSize)); // byte[] array - __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ movl2ptr(off, Address(rsp, 2*wordSize)); // offset - __ addq(buf, off); // + offset - __ movl(crc, Address(rsp, 4*wordSize)); // Initial CRC - } - // Can now load 'len' since we're finished with 'off' - __ movl(len, Address(rsp, wordSize)); // Length - - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len); - // result in rax - - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, r13); // set sp to sender sp - __ jmp(rdi); - - // generate a vanilla native entry as the slow path - __ bind(slow_path); - __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); - return entry; + // Arguments are reversed on java expression stack + // Calculate address of start element + if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) { + __ movptr(buf, Address(rsp, 3*wordSize)); // long buf + __ movl2ptr(off, Address(rsp, 2*wordSize)); // offset + __ addq(buf, off); // + offset + __ movl(crc, Address(rsp, 5*wordSize)); // Initial CRC + } else { + __ movptr(buf, Address(rsp, 3*wordSize)); // byte[] array + __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ movl2ptr(off, Address(rsp, 2*wordSize)); // offset + __ addq(buf, off); // + offset + __ movl(crc, Address(rsp, 4*wordSize)); // Initial CRC } - return NULL; + // Can now load 'len' since we're finished with 'off' + __ movl(len, Address(rsp, wordSize)); // Length + + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len); + // result in rax + + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, r13); // set sp to sender sp + __ jmp(rdi); + + // generate a vanilla native entry as the slow path + __ bind(slow_path); + __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native)); + return entry; } /** @@ -287,49 +283,46 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long address, int off, int end) */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { - if (UseCRC32CIntrinsics) { - address entry = __ pc(); - // Load parameters - const Register crc = c_rarg0; // crc - const Register buf = c_rarg1; // source java byte array address - const Register len = c_rarg2; - const Register off = c_rarg3; // offset - const Register end = len; + assert(UseCRC32CIntrinsics, "this intrinsic is not supported"); + address entry = __ pc(); + // Load parameters + const Register crc = c_rarg0; // crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; + const Register off = c_rarg3; // offset + const Register end = len; - // Arguments are reversed on java expression stack - // Calculate address of start element - if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { - __ movptr(buf, Address(rsp, 3 * wordSize)); // long address - __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset - __ addq(buf, off); // + offset - __ movl(crc, Address(rsp, 5 * wordSize)); // Initial CRC - // Note on 5 * wordSize vs. 4 * wordSize: - // * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end) - // 4 2,3 1 0 - // end starts at SP + 8 - // The Java(R) Virtual Machine Specification Java SE 7 Edition - // 4.10.2.3. Values of Types long and double - // "When calculating operand stack length, values of type long and double have length two." - } else { - __ movptr(buf, Address(rsp, 3 * wordSize)); // byte[] array - __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size - __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset - __ addq(buf, off); // + offset - __ movl(crc, Address(rsp, 4 * wordSize)); // Initial CRC - } - __ movl(end, Address(rsp, wordSize)); // end - __ subl(end, off); // end - off - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len); - // result in rax - // _areturn - __ pop(rdi); // get return address - __ mov(rsp, r13); // set sp to sender sp - __ jmp(rdi); - - return entry; + // Arguments are reversed on java expression stack + // Calculate address of start element + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { + __ movptr(buf, Address(rsp, 3 * wordSize)); // long address + __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset + __ addq(buf, off); // + offset + __ movl(crc, Address(rsp, 5 * wordSize)); // Initial CRC + // Note on 5 * wordSize vs. 4 * wordSize: + // * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end) + // 4 2,3 1 0 + // end starts at SP + 8 + // The Java(R) Virtual Machine Specification Java SE 7 Edition + // 4.10.2.3. Values of Types long and double + // "When calculating operand stack length, values of type long and double have length two." + } else { + __ movptr(buf, Address(rsp, 3 * wordSize)); // byte[] array + __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size + __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset + __ addq(buf, off); // + offset + __ movl(crc, Address(rsp, 4 * wordSize)); // Initial CRC } + __ movl(end, Address(rsp, wordSize)); // end + __ subl(end, off); // end - off + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len); + // result in rax + // _areturn + __ pop(rdi); // get return address + __ mov(rsp, r13); // set sp to sender sp + __ jmp(rdi); - return NULL; + return entry; } /** @@ -337,12 +330,7 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract * java.lang.Float.float16ToFloat(short floatBinary16) */ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16)) { - return nullptr; // Generate a vanilla entry - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); address entry = __ pc(); // r13: the sender's SP @@ -364,12 +352,7 @@ address TemplateInterpreterGenerator::generate_Float_float16ToFloat_entry() { * java.lang.Float.floatToFloat16(float value) */ address TemplateInterpreterGenerator::generate_Float_floatToFloat16_entry() { - // vmIntrinsics checks InlineIntrinsics flag, no need to check it here. - if (!VM_Version::supports_float16() || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_floatToFloat16) || - vmIntrinsics::is_disabled_by_flags(vmIntrinsics::_float16ToFloat)) { - return nullptr; // Generate a vanilla entry - } + assert(VM_Version::supports_float16(), "this intrinsic is not supported"); address entry = __ pc(); // r13: the sender's SP @@ -396,8 +379,6 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // rcx: scratrch // r13: sender sp - if (!InlineIntrinsics) return NULL; // Generate a vanilla entry - address entry_point = __ pc(); // These don't need a safepoint check because they aren't virtually @@ -514,3 +495,9 @@ address TemplateInterpreterGenerator::generate_currentThread() { return entry_point; } +// Not supported +address TemplateInterpreterGenerator::generate_Float_intBitsToFloat_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Float_floatToRawIntBits_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_longBitsToDouble_entry() { return nullptr; } +address TemplateInterpreterGenerator::generate_Double_doubleToRawLongBits_entry() { return nullptr; } + diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 28ead33c608..921bcbce6b6 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "classfile/vmIntrinsics.hpp" #include "code/codeBlob.hpp" #include "compiler/compilerDefinitions.inline.hpp" #include "jvm.h" @@ -3220,3 +3221,19 @@ intx VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) { } } } + +bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) { + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + switch (id) { + case vmIntrinsics::_floatToFloat16: + case vmIntrinsics::_float16ToFloat: + if (!supports_float16()) { + return false; + } + break; + default: + break; + } + return true; +} + diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 226c0848e73..1c4fb3303b4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -764,6 +764,9 @@ public: return supports_f16c() || supports_avx512vl(); } + // Check intrinsic support + static bool is_intrinsic_supported(vmIntrinsicID id); + // there are several insns to force cache line sync to memory which // we can use to ensure mapped non-volatile memory is up to date with // pending in-cache changes. diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 336c2f95aa0..578b171a552 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -28,6 +28,7 @@ #include "compiler/compilerDirectives.hpp" #include "jvm_constants.h" #include "jvm_io.h" +#include "runtime/vm_version.hpp" #include "utilities/xmlstream.hpp" // These are flag-matching functions: @@ -649,9 +650,8 @@ vmIntrinsics::ID vmIntrinsics::find_id(const char* name) { return _none; } -bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) { - vmIntrinsics::ID id = method->intrinsic_id(); - return is_disabled_by_flags(id); +bool vmIntrinsics::is_intrinsic_available(vmIntrinsics::ID id) { + return VM_Version::is_intrinsic_supported(id) && !is_disabled_by_flags(id); } bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 6d1ad75ae68..c72d95203ba 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -1524,10 +1524,7 @@ public: // the corresponding coarse-grained control(2) disables it. static bool is_disabled_by_flags(vmIntrinsics::ID id); - static bool is_disabled_by_flags(const methodHandle& method); - static bool is_intrinsic_available(vmIntrinsics::ID id) { - return !is_disabled_by_flags(id); - } + static bool is_intrinsic_available(vmIntrinsics::ID id); }; #undef VM_INTRINSIC_ENUM diff --git a/src/hotspot/share/compiler/abstractCompiler.hpp b/src/hotspot/share/compiler/abstractCompiler.hpp index 29151b063de..5063daefbff 100644 --- a/src/hotspot/share/compiler/abstractCompiler.hpp +++ b/src/hotspot/share/compiler/abstractCompiler.hpp @@ -126,9 +126,11 @@ class AbstractCompiler : public CHeapObj { // for more details. bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) { + vmIntrinsics::ID id = method->intrinsic_id(); + assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); return is_intrinsic_supported(method) && - !directive->is_intrinsic_disabled(method) && - !vmIntrinsics::is_disabled_by_flags(method); + vmIntrinsics::is_intrinsic_available(id) && + !directive->is_intrinsic_disabled(id); } // Determines if an intrinsic is supported by the compiler, that is, diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index 904aacbaa7d..a15f9974f5e 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -549,8 +549,7 @@ void DirectiveSet::print_inline(outputStream* st) { } } -bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) { - vmIntrinsics::ID id = method->intrinsic_id(); +bool DirectiveSet::is_intrinsic_disabled(vmIntrinsics::ID id) { assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!"); TriBool b = _intrinsic_control_words[vmIntrinsics::as_int(id)]; diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 1bd5c9252c1..f05bec6a104 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -126,7 +126,7 @@ public: bool is_exclusive_copy() { return _directive == nullptr; } bool matches_inline(const methodHandle& method, int inline_action); static DirectiveSet* clone(DirectiveSet const* src); - bool is_intrinsic_disabled(const methodHandle& method); + bool is_intrinsic_disabled(vmIntrinsicID id); static ccstrlist canonicalize_control_intrinsic(ccstrlist option_value); void finalize(outputStream* st); bool is_c1(CompilerDirectives* directive) const; diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index de2b3156e87..03ee3718fbb 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -87,8 +87,6 @@ StubQueue* AbstractInterpreter::_code = nu bool AbstractInterpreter::_notice_safepoints = false; address AbstractInterpreter::_rethrow_exception_entry = nullptr; -address AbstractInterpreter::_native_entry_begin = nullptr; -address AbstractInterpreter::_native_entry_end = nullptr; address AbstractInterpreter::_slow_signature_handler; address AbstractInterpreter::_entry_table [AbstractInterpreter::number_of_method_entries]; address AbstractInterpreter::_native_abi_to_tosca [AbstractInterpreter::number_of_result_handlers]; @@ -135,9 +133,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan case vmIntrinsics::_doubleToRawLongBits: return java_lang_Double_doubleToRawLongBits; case vmIntrinsics::_float16ToFloat: return java_lang_Float_float16ToFloat; case vmIntrinsics::_floatToFloat16: return java_lang_Float_floatToFloat16; -#if defined(AMD64) || defined(AARCH64) || defined(RISCV64) case vmIntrinsics::_currentThread: return java_lang_Thread_currentThread; -#endif #endif // ZERO case vmIntrinsics::_dsin: return java_lang_math_sin; case vmIntrinsics::_dcos: return java_lang_math_cos; @@ -150,7 +146,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan case vmIntrinsics::_fmaD: return java_lang_math_fmaD; case vmIntrinsics::_fmaF: return java_lang_math_fmaF; case vmIntrinsics::_dsqrt: return java_lang_math_sqrt; - case vmIntrinsics::_dsqrt_strict: return java_lang_math_sqrt; + case vmIntrinsics::_dsqrt_strict: return java_lang_math_sqrt_strict; case vmIntrinsics::_Reference_get: return java_lang_ref_reference_get; case vmIntrinsics::_Object_init: if (RegisterFinalizersAtInit && m->code_size() == 1) { @@ -197,7 +193,53 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan return zerolocals; } -void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kind, address entry) { +vmIntrinsics::ID AbstractInterpreter::method_intrinsic(MethodKind kind) { + switch (kind) { + case java_lang_math_sin : return vmIntrinsics::_dsin; + case java_lang_math_cos : return vmIntrinsics::_dcos; + case java_lang_math_tan : return vmIntrinsics::_dtan; + case java_lang_math_abs : return vmIntrinsics::_dabs; + case java_lang_math_log : return vmIntrinsics::_dlog; + case java_lang_math_log10 : return vmIntrinsics::_dlog10; + case java_lang_math_sqrt : return vmIntrinsics::_dsqrt; + case java_lang_math_sqrt_strict : return vmIntrinsics::_dsqrt_strict; + case java_lang_math_pow : return vmIntrinsics::_dpow; + case java_lang_math_exp : return vmIntrinsics::_dexp; + case java_lang_math_fmaD : return vmIntrinsics::_fmaD; + case java_lang_math_fmaF : return vmIntrinsics::_fmaF; + case java_lang_ref_reference_get: return vmIntrinsics::_Reference_get; + case java_util_zip_CRC32_update : return vmIntrinsics::_updateCRC32; + case java_util_zip_CRC32_updateBytes + : return vmIntrinsics::_updateBytesCRC32; + case java_util_zip_CRC32_updateByteBuffer + : return vmIntrinsics::_updateByteBufferCRC32; + case java_util_zip_CRC32C_updateBytes + : return vmIntrinsics::_updateBytesCRC32C; + case java_util_zip_CRC32C_updateDirectByteBuffer + : return vmIntrinsics::_updateDirectByteBufferCRC32C; + case java_lang_Thread_currentThread + : return vmIntrinsics::_currentThread; + case java_lang_Float_intBitsToFloat + : return vmIntrinsics::_intBitsToFloat; + case java_lang_Float_floatToRawIntBits + : return vmIntrinsics::_floatToRawIntBits; + case java_lang_Double_longBitsToDouble + : return vmIntrinsics::_longBitsToDouble; + case java_lang_Double_doubleToRawLongBits + : return vmIntrinsics::_doubleToRawLongBits; + case java_lang_Float_float16ToFloat + : return vmIntrinsics::_float16ToFloat; + case java_lang_Float_floatToFloat16 + : return vmIntrinsics::_floatToFloat16; + + default: + fatal("unexpected method intrinsic kind: %d", kind); + break; + } + return vmIntrinsics::_none; +} + +void AbstractInterpreter::set_entry_for_kind(MethodKind kind, address entry) { assert(kind >= method_handle_invoke_FIRST && kind <= method_handle_invoke_LAST, "late initialization only for MH entry points"); assert(_entry_table[kind] == _entry_table[abstract], "previous value must be AME entry"); @@ -268,16 +310,27 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) { case java_lang_math_cos : tty->print("java_lang_math_cos" ); break; case java_lang_math_tan : tty->print("java_lang_math_tan" ); break; case java_lang_math_abs : tty->print("java_lang_math_abs" ); break; - case java_lang_math_sqrt : tty->print("java_lang_math_sqrt" ); break; case java_lang_math_log : tty->print("java_lang_math_log" ); break; case java_lang_math_log10 : tty->print("java_lang_math_log10" ); break; + case java_lang_math_pow : tty->print("java_lang_math_pow" ); break; + case java_lang_math_exp : tty->print("java_lang_math_exp" ); break; case java_lang_math_fmaD : tty->print("java_lang_math_fmaD" ); break; case java_lang_math_fmaF : tty->print("java_lang_math_fmaF" ); break; + case java_lang_math_sqrt : tty->print("java_lang_math_sqrt" ); break; + case java_lang_math_sqrt_strict : tty->print("java_lang_math_sqrt_strict"); break; case java_util_zip_CRC32_update : tty->print("java_util_zip_CRC32_update"); break; case java_util_zip_CRC32_updateBytes : tty->print("java_util_zip_CRC32_updateBytes"); break; case java_util_zip_CRC32_updateByteBuffer : tty->print("java_util_zip_CRC32_updateByteBuffer"); break; case java_util_zip_CRC32C_updateBytes : tty->print("java_util_zip_CRC32C_updateBytes"); break; case java_util_zip_CRC32C_updateDirectByteBuffer: tty->print("java_util_zip_CRC32C_updateDirectByteByffer"); break; + case java_lang_ref_reference_get : tty->print("java_lang_ref_reference_get"); break; + case java_lang_Thread_currentThread : tty->print("java_lang_Thread_currentThread"); break; + case java_lang_Float_intBitsToFloat : tty->print("java_lang_Float_intBitsToFloat"); break; + case java_lang_Float_floatToRawIntBits : tty->print("java_lang_Float_floatToRawIntBits"); break; + case java_lang_Double_longBitsToDouble : tty->print("java_lang_Double_longBitsToDouble"); break; + case java_lang_Double_doubleToRawLongBits : tty->print("java_lang_Double_doubleToRawLongBits"); break; + case java_lang_Float_float16ToFloat : tty->print("java_lang_Float_float16ToFloat"); break; + case java_lang_Float_floatToFloat16 : tty->print("java_lang_Float_floatToFloat16"); break; default: if (kind >= method_handle_invoke_FIRST && kind <= method_handle_invoke_LAST) { diff --git a/src/hotspot/share/interpreter/abstractInterpreter.hpp b/src/hotspot/share/interpreter/abstractInterpreter.hpp index 16878695d04..e487b152b76 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.hpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.hpp @@ -74,6 +74,7 @@ class AbstractInterpreter: AllStatic { java_lang_math_tan, // implementation of java.lang.Math.tan (x) java_lang_math_abs, // implementation of java.lang.Math.abs (x) java_lang_math_sqrt, // implementation of java.lang.Math.sqrt (x) + java_lang_math_sqrt_strict, // implementation of java.lang.StrictMath.sqrt(x) java_lang_math_log, // implementation of java.lang.Math.log (x) java_lang_math_log10, // implementation of java.lang.Math.log10 (x) java_lang_math_pow, // implementation of java.lang.Math.pow (x,y) @@ -105,6 +106,9 @@ class AbstractInterpreter: AllStatic { return vmIntrinsics::_none; } + // Conversion from the above enum to vmIntrinsics::ID + static vmIntrinsics::ID method_intrinsic(MethodKind kind); + enum SomeConstants { number_of_result_handlers = 10 // number of result handlers for native calls }; @@ -114,9 +118,6 @@ class AbstractInterpreter: AllStatic { static bool _notice_safepoints; // true if safepoints are activated - static address _native_entry_begin; // Region for native entry code - static address _native_entry_end; - // method entry points static address _entry_table[number_of_method_entries]; // entry points for a given method static address _native_abi_to_tosca[number_of_result_handlers]; // for native method result handlers @@ -223,7 +224,6 @@ class AbstractInterpreter: AllStatic { static address slow_signature_handler() { return _slow_signature_handler; } static address result_handler(BasicType type) { return _native_abi_to_tosca[BasicType_as_index(type)]; } static int BasicType_as_index(BasicType type); // computes index into result_handler_by_index table - static bool in_native_entry(address pc) { return _native_entry_begin <= pc && pc < _native_entry_end; } // Debugging/printing static void print(); // prints the interpreter code diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 088c0086220..9cd6f5ceffb 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -177,9 +177,9 @@ void TemplateInterpreterGenerator::generate_all() { -#define method_entry(kind) \ - { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ - Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ +#define method_entry(kind) \ + { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ + Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, false); \ } // all non-native method kinds @@ -194,6 +194,7 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(java_lang_math_tan ) method_entry(java_lang_math_abs ) method_entry(java_lang_math_sqrt ) + method_entry(java_lang_math_sqrt_strict) method_entry(java_lang_math_log ) method_entry(java_lang_math_log10) method_entry(java_lang_math_exp ) @@ -201,33 +202,41 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(java_lang_math_fmaF ) method_entry(java_lang_math_fmaD ) method_entry(java_lang_ref_reference_get) -#if defined(AMD64) || defined(AARCH64) || defined(RISCV64) - method_entry(java_lang_Thread_currentThread) -#endif AbstractInterpreter::initialize_method_handle_entries(); - // all native method kinds (must be one contiguous block) - Interpreter::_native_entry_begin = Interpreter::code()->code_end(); - method_entry(native) - method_entry(native_synchronized) - Interpreter::_native_entry_end = Interpreter::code()->code_end(); - - method_entry(java_util_zip_CRC32_update) - method_entry(java_util_zip_CRC32_updateBytes) - method_entry(java_util_zip_CRC32_updateByteBuffer) method_entry(java_util_zip_CRC32C_updateBytes) method_entry(java_util_zip_CRC32C_updateDirectByteBuffer) - method_entry(java_lang_Float_intBitsToFloat); - method_entry(java_lang_Float_floatToRawIntBits); - method_entry(java_lang_Double_longBitsToDouble); - method_entry(java_lang_Double_doubleToRawLongBits); - method_entry(java_lang_Float_float16ToFloat); method_entry(java_lang_Float_floatToFloat16); #undef method_entry + // all native method kinds +#define native_method_entry(kind) \ + { CodeletMark cm(_masm, "native method entry point (kind = " #kind ")"); \ + Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, true); \ + } + + native_method_entry(native) + native_method_entry(native_synchronized) + + // Entries to intrinsics for native methods should follow + // entries for `native` methods to use the same address in case + // intrinsic is disabled. + native_method_entry(java_lang_Thread_currentThread) + + native_method_entry(java_util_zip_CRC32_update) + native_method_entry(java_util_zip_CRC32_updateBytes) + native_method_entry(java_util_zip_CRC32_updateByteBuffer) + + native_method_entry(java_lang_Float_intBitsToFloat) + native_method_entry(java_lang_Float_floatToRawIntBits) + native_method_entry(java_lang_Double_longBitsToDouble) + native_method_entry(java_lang_Double_doubleToRawLongBits) + +#undef native_method_entry + // Bytecodes set_entry_points_for_all_bytes(); @@ -397,74 +406,22 @@ void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState t // Generate method entries address TemplateInterpreterGenerator::generate_method_entry( - AbstractInterpreter::MethodKind kind) { + AbstractInterpreter::MethodKind kind, bool native) { // determine code generation flags - bool native = false; bool synchronized = false; address entry_point = nullptr; switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : native = true; break; - case Interpreter::native_synchronized : native = true; synchronized = true; break; + case Interpreter::zerolocals : break; + case Interpreter::zerolocals_synchronized: synchronized = true; break; + case Interpreter::native : break; + case Interpreter::native_synchronized : synchronized = true; break; case Interpreter::empty : break; case Interpreter::getter : break; case Interpreter::setter : break; case Interpreter::abstract : entry_point = generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : // fall thru - case Interpreter::java_lang_math_fmaD : // fall thru - case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get - : entry_point = generate_Reference_get_entry(); break; - case Interpreter::java_util_zip_CRC32_update - : native = true; entry_point = generate_CRC32_update_entry(); break; - case Interpreter::java_util_zip_CRC32_updateBytes - : // fall thru - case Interpreter::java_util_zip_CRC32_updateByteBuffer - : native = true; entry_point = generate_CRC32_updateBytes_entry(kind); break; - case Interpreter::java_util_zip_CRC32C_updateBytes - : // fall thru - case Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer - : entry_point = generate_CRC32C_updateBytes_entry(kind); break; -#if defined(AMD64) || defined(AARCH64) || defined(RISCV64) - case Interpreter::java_lang_Thread_currentThread - : entry_point = generate_currentThread(); break; -#endif - case Interpreter::java_lang_Float_float16ToFloat - : entry_point = generate_Float_float16ToFloat_entry(); break; - case Interpreter::java_lang_Float_floatToFloat16 - : entry_point = generate_Float_floatToFloat16_entry(); break; -#ifdef IA32 - // On x86_32 platforms, a special entry is generated for the following four methods. - // On other platforms the normal entry is used to enter these methods. - case Interpreter::java_lang_Float_intBitsToFloat - : native = true; entry_point = generate_Float_intBitsToFloat_entry(); break; - case Interpreter::java_lang_Float_floatToRawIntBits - : native = true; entry_point = generate_Float_floatToRawIntBits_entry(); break; - case Interpreter::java_lang_Double_longBitsToDouble - : native = true; entry_point = generate_Double_longBitsToDouble_entry(); break; - case Interpreter::java_lang_Double_doubleToRawLongBits - : native = true; entry_point = generate_Double_doubleToRawLongBits_entry(); break; -#else - case Interpreter::java_lang_Float_intBitsToFloat: - case Interpreter::java_lang_Float_floatToRawIntBits: - case Interpreter::java_lang_Double_longBitsToDouble: - case Interpreter::java_lang_Double_doubleToRawLongBits: - native = true; - break; -#endif // !IA32 default: - fatal("unexpected method kind: %d", kind); + entry_point = generate_intrinsic_entry(kind); // process the rest break; } @@ -487,3 +444,62 @@ address TemplateInterpreterGenerator::generate_method_entry( return entry_point; } + +// Generate intrinsic method entries +address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpreter::MethodKind kind) { + if (!InlineIntrinsics || !vmIntrinsics::is_intrinsic_available(AbstractInterpreter::method_intrinsic(kind))) { + return nullptr; + } + + address entry_point = nullptr; + + switch (kind) { + case Interpreter::java_lang_math_sin : // fall thru + case Interpreter::java_lang_math_cos : // fall thru + case Interpreter::java_lang_math_tan : // fall thru + case Interpreter::java_lang_math_abs : // fall thru + case Interpreter::java_lang_math_log : // fall thru + case Interpreter::java_lang_math_log10 : // fall thru + case Interpreter::java_lang_math_sqrt : // fall thru + case Interpreter::java_lang_math_pow : // fall thru + case Interpreter::java_lang_math_exp : // fall thru + case Interpreter::java_lang_math_fmaD : // fall thru + case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; + case Interpreter::java_lang_math_sqrt_strict + : entry_point = generate_math_entry(Interpreter::java_lang_math_sqrt); break; + case Interpreter::java_lang_ref_reference_get + : entry_point = generate_Reference_get_entry(); break; + case Interpreter::java_util_zip_CRC32_update + : entry_point = generate_CRC32_update_entry(); break; + case Interpreter::java_util_zip_CRC32_updateBytes + : // fall thru + case Interpreter::java_util_zip_CRC32_updateByteBuffer + : entry_point = generate_CRC32_updateBytes_entry(kind); break; + case Interpreter::java_util_zip_CRC32C_updateBytes + : // fall thru + case Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer + : entry_point = generate_CRC32C_updateBytes_entry(kind); break; + case Interpreter::java_lang_Thread_currentThread + : entry_point = generate_currentThread(); break; + case Interpreter::java_lang_Float_float16ToFloat + : entry_point = generate_Float_float16ToFloat_entry(); break; + case Interpreter::java_lang_Float_floatToFloat16 + : entry_point = generate_Float_floatToFloat16_entry(); break; + + // On x86_32 platforms, a special entry is generated for the following four methods. + // On other platforms the native entry is used to enter these methods. + case Interpreter::java_lang_Float_intBitsToFloat + : entry_point = generate_Float_intBitsToFloat_entry(); break; + case Interpreter::java_lang_Float_floatToRawIntBits + : entry_point = generate_Float_floatToRawIntBits_entry(); break; + case Interpreter::java_lang_Double_longBitsToDouble + : entry_point = generate_Double_longBitsToDouble_entry(); break; + case Interpreter::java_lang_Double_doubleToRawLongBits + : entry_point = generate_Double_doubleToRawLongBits_entry(); break; + default: + fatal("unexpected intrinsic method kind: %d", kind); + break; + } + return entry_point; +} + diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp index 726e0495650..bcccff2fe82 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp @@ -84,7 +84,10 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { void generate_all(); // entry point generator - address generate_method_entry(AbstractInterpreter::MethodKind kind); + address generate_method_entry(AbstractInterpreter::MethodKind kind, bool native); + + // generate intrinsic method entries + address generate_intrinsic_entry(AbstractInterpreter::MethodKind kind); address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); @@ -94,15 +97,11 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { address generate_CRC32_update_entry(); address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind); address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind); -#if defined(AMD64) || defined(AARCH64) || defined(RISCV64) address generate_currentThread(); -#endif -#ifdef IA32 address generate_Float_intBitsToFloat_entry(); address generate_Float_floatToRawIntBits_entry(); address generate_Double_longBitsToDouble_entry(); address generate_Double_doubleToRawLongBits_entry(); -#endif // IA32 address generate_Float_float16ToFloat_entry(); address generate_Float_floatToFloat16_entry(); diff --git a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp index 72fdd151c6b..4940662143e 100644 --- a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp @@ -66,10 +66,8 @@ void ZeroInterpreterGenerator::generate_all() { AbstractInterpreter::initialize_method_handle_entries(); - Interpreter::_native_entry_begin = Interpreter::code()->code_end(); method_entry(native); method_entry(native_synchronized); - Interpreter::_native_entry_end = Interpreter::code()->code_end(); } #undef method_entry diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index f809b7d0fbf..f5bfb06d2e7 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -180,7 +180,7 @@ void C2Compiler::print_timers() { Compile::print_timers(); } -bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virtual) { +bool C2Compiler::is_intrinsic_supported(const methodHandle& method) { vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -188,20 +188,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt return false; } - // Only Object.hashCode and Object.clone intrinsics implement also a virtual - // dispatch because calling both methods is expensive but both methods are - // frequently overridden. All other intrinsics implement only a non-virtual - // dispatch. - if (is_virtual) { - switch (id) { - case vmIntrinsics::_hashCode: - case vmIntrinsics::_clone: - break; - default: - return false; - } - } - switch (id) { case vmIntrinsics::_compressStringC: case vmIntrinsics::_compressStringB: diff --git a/src/hotspot/share/opto/c2compiler.hpp b/src/hotspot/share/opto/c2compiler.hpp index d11463f15a8..bcb6d70e5a4 100644 --- a/src/hotspot/share/opto/c2compiler.hpp +++ b/src/hotspot/share/opto/c2compiler.hpp @@ -61,13 +61,7 @@ public: // possible for only a limited set of available intrinsics whereas // a non-virtual dispatch is possible for all available intrinsics.) // Return false otherwise. - virtual bool is_intrinsic_supported(const methodHandle& method) { - return is_intrinsic_supported(method, false); - } - - // Check if the compiler supports an intrinsic for 'method' given the - // the dispatch mode specified by the 'is_virtual' parameter. - bool is_intrinsic_supported(const methodHandle& method, bool is_virtual); + virtual bool is_intrinsic_supported(const methodHandle& method); // Initial size of the code buffer (may be increased at runtime) static int initial_code_buffer_size(int const_size = initial_const_capacity); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index ecc15a35257..28bde8e4df7 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -77,10 +77,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { // methods access VM-internal data. VM_ENTRY_MARK; methodHandle mh(THREAD, m->get_Method()); - is_available = compiler != nullptr && compiler->is_intrinsic_supported(mh, is_virtual) && - !C->directive()->is_intrinsic_disabled(mh) && - !vmIntrinsics::is_disabled_by_flags(mh); - + is_available = compiler != nullptr && compiler->is_intrinsic_available(mh, C->directive()); + if (is_available && is_virtual) { + is_available = vmIntrinsics::does_virtual_dispatch(id); + } } if (is_available) { diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index a192d41b739..f610d58e287 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -42,6 +42,7 @@ typedef enum { } VirtualizationType; class outputStream; +enum class vmIntrinsicID; // Abstract_VM_Version provides information about the VM. @@ -181,6 +182,10 @@ class Abstract_VM_Version: AllStatic { // Does platform support float16 instructions? static bool supports_float16() { return false; } + + // Does this CPU support this intrinsic? + static bool is_intrinsic_supported(vmIntrinsicID id) { return true; } + static bool print_matching_lines_from_file(const char* filename, outputStream* st, const char* keywords_to_match[]); protected: diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index e2837f71cbf..64a8e69e8f8 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1194,7 +1194,7 @@ const int ObjectAlignmentInBytes = 8; "Trace frequency based inlining") \ \ develop_pd(bool, InlineIntrinsics, \ - "Inline intrinsics that can be statically resolved") \ + "Use intrinsics in Interpreter that can be statically resolved") \ \ product_pd(bool, ProfileInterpreter, \ "Profile at the bytecode level during interpretation") \ diff --git a/test/hotspot/jtreg/compiler/floatingpoint/NaNTest.java b/test/hotspot/jtreg/compiler/floatingpoint/NaNTest.java index 63724360911..959647014ca 100644 --- a/test/hotspot/jtreg/compiler/floatingpoint/NaNTest.java +++ b/test/hotspot/jtreg/compiler/floatingpoint/NaNTest.java @@ -83,8 +83,9 @@ public class NaNTest { // signaling NaNs. if (Platform.isX86()) { int sse = WHITE_BOX.getIntVMFlag("UseSSE").intValue(); - expectStableFloats = (sse >= 1); - expectStableDoubles = (sse >= 2); + boolean stubsPresent = WHITE_BOX.getBooleanVMFlag("InlineIntrinsics"); + expectStableFloats = (sse >= 1) && stubsPresent; + expectStableDoubles = (sse >= 2) && stubsPresent; } if (expectStableFloats) {