8196786: [PPC64+s390] ConstantDynamic support

Reviewed-by: psandoz, dsamersoff
This commit is contained in:
Martin Doerr 2018-02-13 17:38:03 +01:00
parent 4f8c5b6949
commit eb3ec99500
7 changed files with 277 additions and 37 deletions

View File

@ -492,6 +492,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
// Add in the index.
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
// The resulting oop is null if the reference is not yet resolved.
// It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)

View File

@ -314,7 +314,7 @@ void TemplateTable::ldc(bool wide) {
Rcpool = R3_ARG1;
transition(vtos, vtos);
Label notInt, notClass, exit;
Label notInt, notFloat, notClass, exit;
__ get_cpool_and_tags(Rcpool, Rscratch2); // Set Rscratch2 = &tags.
if (wide) { // Read index.
@ -356,13 +356,16 @@ void TemplateTable::ldc(bool wide) {
__ align(32, 12);
__ bind(notInt);
#ifdef ASSERT
// String and Object are rewritten to fast_aldc
__ cmpdi(CCR0, Rscratch2, JVM_CONSTANT_Float);
__ asm_assert_eq("unexpected type", 0x8765);
#endif
__ bne(CCR0, notFloat);
__ lfsx(F15_ftos, Rcpool, Rscratch1);
__ push(ftos);
__ b(exit);
__ align(32, 12);
// assume the tag is for condy; if not, the VM runtime will tell us
__ bind(notFloat);
condy_helper(exit);
__ align(32, 12);
__ bind(exit);
@ -380,6 +383,19 @@ void TemplateTable::fast_aldc(bool wide) {
// non-null object (CallSite, etc.)
__ get_cache_index_at_bcp(Rscratch, 1, index_size); // Load index.
__ load_resolved_reference_at_index(R17_tos, Rscratch, &is_null);
// Convert null sentinel to NULL.
int simm16_rest = __ load_const_optimized(Rscratch, Universe::the_null_sentinel_addr(), R0, true);
__ ld(Rscratch, simm16_rest, Rscratch);
__ cmpld(CCR0, R17_tos, Rscratch);
if (VM_Version::has_isel()) {
__ isel_0(R17_tos, CCR0, Assembler::equal);
} else {
Label not_sentinel;
__ bne(CCR0, not_sentinel);
__ li(R17_tos, 0);
__ bind(not_sentinel);
}
__ verify_oop(R17_tos);
__ dispatch_epilog(atos, Bytecodes::length_for(bytecode()));
@ -395,7 +411,7 @@ void TemplateTable::fast_aldc(bool wide) {
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
Label Llong, Lexit;
Label not_double, not_long, exit;
Register Rindex = R11_scratch1,
Rcpool = R12_scratch2,
@ -410,23 +426,129 @@ void TemplateTable::ldc2_w() {
__ addi(Rtag, Rtag, tags_offset);
__ lbzx(Rtag, Rtag, Rindex);
__ sldi(Rindex, Rindex, LogBytesPerWord);
__ cmpdi(CCR0, Rtag, JVM_CONSTANT_Double);
__ bne(CCR0, Llong);
// A double can be placed at word-aligned locations in the constant pool.
// Check out Conversions.java for an example.
// Also ConstantPool::header_size() is 20, which makes it very difficult
// to double-align double on the constant pool. SG, 11/7/97
__ bne(CCR0, not_double);
__ lfdx(F15_ftos, Rcpool, Rindex);
__ push(dtos);
__ b(Lexit);
__ b(exit);
__ bind(Llong);
__ bind(not_double);
__ cmpdi(CCR0, Rtag, JVM_CONSTANT_Long);
__ bne(CCR0, not_long);
__ ldx(R17_tos, Rcpool, Rindex);
__ push(ltos);
__ b(exit);
__ bind(Lexit);
__ bind(not_long);
condy_helper(exit);
__ align(32, 12);
__ bind(exit);
}
void TemplateTable::condy_helper(Label& Done) {
const Register obj = R31;
const Register off = R11_scratch1;
const Register flags = R12_scratch2;
const Register rarg = R4_ARG2;
__ li(rarg, (int)bytecode());
call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
__ get_vm_result_2(flags);
// VMr = obj = base address to find primitive value to push
// VMr2 = flags = (tos, off) using format of CPCE::_flags
__ andi(off, flags, ConstantPoolCacheEntry::field_index_mask);
// What sort of thing are we loading?
__ rldicl(flags, flags, 64-ConstantPoolCacheEntry::tos_state_shift, 64-ConstantPoolCacheEntry::tos_state_bits);
switch (bytecode()) {
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
{
// tos in (itos, ftos, stos, btos, ctos, ztos)
Label notInt, notFloat, notShort, notByte, notChar, notBool;
__ cmplwi(CCR0, flags, itos);
__ bne(CCR0, notInt);
// itos
__ lwax(R17_tos, obj, off);
__ push(itos);
__ b(Done);
__ bind(notInt);
__ cmplwi(CCR0, flags, ftos);
__ bne(CCR0, notFloat);
// ftos
__ lfsx(F15_ftos, obj, off);
__ push(ftos);
__ b(Done);
__ bind(notFloat);
__ cmplwi(CCR0, flags, stos);
__ bne(CCR0, notShort);
// stos
__ lhax(R17_tos, obj, off);
__ push(stos);
__ b(Done);
__ bind(notShort);
__ cmplwi(CCR0, flags, btos);
__ bne(CCR0, notByte);
// btos
__ lbzx(R17_tos, obj, off);
__ extsb(R17_tos, R17_tos);
__ push(btos);
__ b(Done);
__ bind(notByte);
__ cmplwi(CCR0, flags, ctos);
__ bne(CCR0, notChar);
// ctos
__ lhzx(R17_tos, obj, off);
__ push(ctos);
__ b(Done);
__ bind(notChar);
__ cmplwi(CCR0, flags, ztos);
__ bne(CCR0, notBool);
// ztos
__ lbzx(R17_tos, obj, off);
__ push(ztos);
__ b(Done);
__ bind(notBool);
break;
}
case Bytecodes::_ldc2_w:
{
Label notLong, notDouble;
__ cmplwi(CCR0, flags, ltos);
__ bne(CCR0, notLong);
// ltos
__ ldx(R17_tos, obj, off);
__ push(ltos);
__ b(Done);
__ bind(notLong);
__ cmplwi(CCR0, flags, dtos);
__ bne(CCR0, notDouble);
// dtos
__ lfdx(F15_ftos, obj, off);
__ push(dtos);
__ b(Done);
__ bind(notDouble);
break;
}
default:
ShouldNotReachHere();
}
__ stop("bad ldc/condy");
}
// Get the locals index located in the bytecode stream at bcp + offset.

View File

@ -389,6 +389,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
#endif
z_agr(result, index); // Address of indexed array element.
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
// The resulting oop is null if the reference is not yet resolved.
// It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)

View File

@ -450,7 +450,7 @@ void TemplateTable::sipush() {
void TemplateTable::ldc(bool wide) {
transition(vtos, vtos);
Label call_ldc, notFloat, notClass, Done;
Label call_ldc, notFloat, notClass, notInt, Done;
const Register RcpIndex = Z_tmp_1;
const Register Rtags = Z_ARG2;
@ -500,22 +500,17 @@ void TemplateTable::ldc(bool wide) {
__ z_bru(Done);
__ bind(notFloat);
#ifdef ASSERT
{
Label L;
__ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
__ z_bre(L);
// String and Object are rewritten to fast_aldc.
__ stop("unexpected tag type in ldc");
__ bind(L);
}
#endif
__ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
__ z_brne(notInt);
// itos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, RcpOffset, base_offset), false);
__ push_i(Z_tos);
__ z_bru(Done);
// assume the tag is for condy; if not, the VM runtime will tell us
__ bind(notInt);
condy_helper(Done);
__ bind(Done);
}
@ -528,15 +523,23 @@ void TemplateTable::fast_aldc(bool wide) {
const Register index = Z_tmp_2;
int index_size = wide ? sizeof(u2) : sizeof(u1);
Label L_resolved;
Label L_do_resolve, L_resolved;
// We are resolved if the resolved reference cache entry contains a
// non-null object (CallSite, etc.).
__ get_cache_index_at_bcp(index, 1, index_size); // Load index.
__ load_resolved_reference_at_index(Z_tos, index);
__ z_ltgr(Z_tos, Z_tos);
__ z_brne(L_resolved);
__ z_bre(L_do_resolve);
// Convert null sentinel to NULL.
__ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr());
__ z_cg(Z_tos, Address(Z_R1_scratch));
__ z_brne(L_resolved);
__ clear_reg(Z_tos);
__ z_bru(L_resolved);
__ bind(L_do_resolve);
// First time invocation - must resolve first.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
__ load_const_optimized(Z_ARG1, (int)bytecode());
@ -548,7 +551,7 @@ void TemplateTable::fast_aldc(bool wide) {
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
Label Long, Done;
Label notDouble, notLong, Done;
// Z_tmp_1 = index of cp entry
__ get_2_byte_integer_at_bcp(Z_tmp_1, 1, InterpreterMacroAssembler::Unsigned);
@ -566,21 +569,132 @@ void TemplateTable::ldc2_w() {
// Check type.
__ z_cli(0, Z_tos, JVM_CONSTANT_Double);
__ z_brne(Long);
__ z_brne(notDouble);
// dtos
__ mem2freg_opt(Z_ftos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_d();
__ z_bru(Done);
__ bind(Long);
__ bind(notDouble);
__ z_cli(0, Z_tos, JVM_CONSTANT_Long);
__ z_brne(notLong);
// ltos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_l();
__ z_bru(Done);
__ bind(notLong);
condy_helper(Done);
__ bind(Done);
}
void TemplateTable::condy_helper(Label& Done) {
const Register obj = Z_tmp_1;
const Register off = Z_tmp_2;
const Register flags = Z_ARG1;
const Register rarg = Z_ARG2;
__ load_const_optimized(rarg, (int)bytecode());
call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
__ get_vm_result_2(flags);
// VMr = obj = base address to find primitive value to push
// VMr2 = flags = (tos, off) using format of CPCE::_flags
assert(ConstantPoolCacheEntry::field_index_mask == 0xffff, "or use other instructions");
__ z_llghr(off, flags);
const Address field(obj, off);
// What sort of thing are we loading?
__ z_srl(flags, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask flags for tos_state after the above shift.
ConstantPoolCacheEntry::verify_tos_state_shift();
switch (bytecode()) {
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
{
// tos in (itos, ftos, stos, btos, ctos, ztos)
Label notInt, notFloat, notShort, notByte, notChar, notBool;
__ z_cghi(flags, itos);
__ z_brne(notInt);
// itos
__ z_l(Z_tos, field);
__ push(itos);
__ z_bru(Done);
__ bind(notInt);
__ z_cghi(flags, ftos);
__ z_brne(notFloat);
// ftos
__ z_le(Z_ftos, field);
__ push(ftos);
__ z_bru(Done);
__ bind(notFloat);
__ z_cghi(flags, stos);
__ z_brne(notShort);
// stos
__ z_lh(Z_tos, field);
__ push(stos);
__ z_bru(Done);
__ bind(notShort);
__ z_cghi(flags, btos);
__ z_brne(notByte);
// btos
__ z_lb(Z_tos, field);
__ push(btos);
__ z_bru(Done);
__ bind(notByte);
__ z_cghi(flags, ctos);
__ z_brne(notChar);
// ctos
__ z_llh(Z_tos, field);
__ push(ctos);
__ z_bru(Done);
__ bind(notChar);
__ z_cghi(flags, ztos);
__ z_brne(notBool);
// ztos
__ z_lb(Z_tos, field);
__ push(ztos);
__ z_bru(Done);
__ bind(notBool);
break;
}
case Bytecodes::_ldc2_w:
{
Label notLong, notDouble;
__ z_cghi(flags, ltos);
__ z_brne(notLong);
// ltos
__ z_lg(Z_tos, field);
__ push(ltos);
__ z_bru(Done);
__ bind(notLong);
__ z_cghi(flags, dtos);
__ z_brne(notDouble);
// dtos
__ z_ld(Z_ftos, field);
__ push(dtos);
__ z_bru(Done);
__ bind(notDouble);
break;
}
default:
ShouldNotReachHere();
}
__ stop("bad ldc/condy");
}
void TemplateTable::locals_index(Register reg, int offset) {
__ z_llgc(reg, at_bcp(offset));
__ z_lcgr(reg);

View File

@ -25,7 +25,7 @@
* @test
* @bug 8186211
* @summary Test basic invocation of multiple ldc's of the same dynamic constant that fail resolution
* @requires os.arch == "x86_64" | os.arch=="aarch64"
* @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyRepeatFailedResolution

View File

@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test for condy BSMs returning primitive values or null
* @requires os.arch=="x86_64" | os.arch=="aarch64"
* @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyReturnPrimitiveTest

View File

@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test bootstrap methods returning the wrong type
* @requires os.arch == "x86_64" | os.arch=="aarch64"
* @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
* @run testng CondyWrongType