8303415: Add VM_Version::is_intrinsic_supported(id)

Reviewed-by: thartmann, dholmes
This commit is contained in:
Vladimir Kozlov 2023-03-14 12:20:14 +00:00
parent 31680b2bcf
commit ec1eb00ed3
25 changed files with 851 additions and 829 deletions

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

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

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

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

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

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

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

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

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

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

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

@ -126,9 +126,11 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
// 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,

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

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

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

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

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

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

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

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

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

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

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

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

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