mirror of
https://github.com/openjdk/jdk19u.git
synced 2025-12-11 09:24:36 -06:00
Merge
This commit is contained in:
commit
12b22ec367
@ -394,7 +394,7 @@ For terms of use, see http://www.unicode.org/copyright.html
|
||||
<type name="tvfun" description="Funafuti, Tuvalu" alias="Pacific/Funafuti"/>
|
||||
<type name="twtpe" description="Taipei, Taiwan" alias="Asia/Taipei ROC"/>
|
||||
<type name="tzdar" description="Dar es Salaam, Tanzania" alias="Africa/Dar_es_Salaam"/>
|
||||
<type name="uaiev" description="Kyiv, Ukraine" alias="Europe/Kiev"/>
|
||||
<type name="uaiev" description="Kyiv, Ukraine" alias="Europe/Kiev Europe/Kyiv"/>
|
||||
<type name="uaozh" description="Zaporizhia (Zaporozhye), Ukraine" alias="Europe/Zaporozhye"/>
|
||||
<type name="uasip" description="Simferopol, Ukraine" alias="Europe/Simferopol"/>
|
||||
<type name="uauzh" description="Uzhhorod (Uzhgorod), Ukraine" alias="Europe/Uzhgorod"/>
|
||||
|
||||
@ -619,8 +619,23 @@ address MacroAssembler::trampoline_call1(Address entry, CodeBuffer* cbuf, bool c
|
||||
|| entry.rspec().type() == relocInfo::static_call_type
|
||||
|| entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type");
|
||||
|
||||
bool need_trampoline = far_branches();
|
||||
if (!need_trampoline && entry.rspec().type() == relocInfo::runtime_call_type && !CodeCache::contains(entry.target())) {
|
||||
// If it is a runtime call of an address outside small CodeCache,
|
||||
// we need to check whether it is in range.
|
||||
address target = entry.target();
|
||||
assert(target < CodeCache::low_bound() || target >= CodeCache::high_bound(), "target is inside CodeCache");
|
||||
// Case 1: -------T-------L====CodeCache====H-------
|
||||
// ^-------longest branch---|
|
||||
// Case 2: -------L====CodeCache====H-------T-------
|
||||
// |-------longest branch ---^
|
||||
address longest_branch_start = (target < CodeCache::low_bound()) ? CodeCache::high_bound() - NativeInstruction::instruction_size
|
||||
: CodeCache::low_bound();
|
||||
need_trampoline = !reachable_from_branch_at(longest_branch_start, target);
|
||||
}
|
||||
|
||||
// We need a trampoline if branches are far.
|
||||
if (far_branches()) {
|
||||
if (need_trampoline) {
|
||||
bool in_scratch_emit_size = false;
|
||||
#ifdef COMPILER2
|
||||
if (check_emit_size) {
|
||||
@ -643,7 +658,7 @@ address MacroAssembler::trampoline_call1(Address entry, CodeBuffer* cbuf, bool c
|
||||
|
||||
if (cbuf) cbuf->set_insts_mark();
|
||||
relocate(entry.rspec());
|
||||
if (!far_branches()) {
|
||||
if (!need_trampoline) {
|
||||
bl(entry.target());
|
||||
} else {
|
||||
bl(pc());
|
||||
@ -3355,7 +3370,7 @@ void MacroAssembler::kernel_crc32_using_crc32(Register crc, Register buf,
|
||||
crc32x(crc, crc, tmp2);
|
||||
crc32x(crc, crc, tmp3);
|
||||
br(Assembler::GE, CRC_by32_loop);
|
||||
cmn(len, 32);
|
||||
cmn(len, (u1)32);
|
||||
br(Assembler::NE, CRC_less32);
|
||||
b(L_exit);
|
||||
|
||||
@ -3418,7 +3433,7 @@ void MacroAssembler::kernel_crc32_using_crc32(Register crc, Register buf,
|
||||
|
||||
sub(len, len, 64);
|
||||
add(buf, buf, 8);
|
||||
cmn(len, 128);
|
||||
cmn(len, (u1)128);
|
||||
br(Assembler::NE, CRC_less64);
|
||||
BIND(L_exit);
|
||||
mvnw(crc, crc);
|
||||
@ -3652,7 +3667,7 @@ void MacroAssembler::kernel_crc32c_using_crc32c(Register crc, Register buf,
|
||||
crc32cx(crc, crc, tmp2);
|
||||
crc32cx(crc, crc, tmp3);
|
||||
br(Assembler::GE, CRC_by32_loop);
|
||||
cmn(len, 32);
|
||||
cmn(len, (u1)32);
|
||||
br(Assembler::NE, CRC_less32);
|
||||
b(L_exit);
|
||||
|
||||
@ -3715,7 +3730,7 @@ void MacroAssembler::kernel_crc32c_using_crc32c(Register crc, Register buf,
|
||||
|
||||
sub(len, len, 64);
|
||||
add(buf, buf, 8);
|
||||
cmn(len, 128);
|
||||
cmn(len, (u1)128);
|
||||
br(Assembler::NE, CRC_less64);
|
||||
BIND(L_exit);
|
||||
}
|
||||
|
||||
@ -197,8 +197,11 @@ class MacroAssembler: public Assembler {
|
||||
inline void cmp(Register Rd, unsigned char imm8) { subs(zr, Rd, imm8); }
|
||||
inline void cmp(Register Rd, unsigned imm) = delete;
|
||||
|
||||
inline void cmnw(Register Rd, unsigned imm) { addsw(zr, Rd, imm); }
|
||||
inline void cmn(Register Rd, unsigned imm) { adds(zr, Rd, imm); }
|
||||
template<class T>
|
||||
inline void cmnw(Register Rd, T imm) { addsw(zr, Rd, imm); }
|
||||
|
||||
inline void cmn(Register Rd, unsigned char imm8) { adds(zr, Rd, imm8); }
|
||||
inline void cmn(Register Rd, unsigned imm) = delete;
|
||||
|
||||
void cset(Register Rd, Assembler::Condition cond) {
|
||||
csinc(Rd, zr, zr, ~cond);
|
||||
|
||||
@ -133,7 +133,7 @@
|
||||
// Entry frames
|
||||
// n.b. these values are determined by the layout defined in
|
||||
// stubGenerator for the Java call stub
|
||||
entry_frame_after_call_words = 22,
|
||||
entry_frame_after_call_words = 34,
|
||||
entry_frame_call_wrapper_offset = -10,
|
||||
|
||||
// we don't need a save area
|
||||
|
||||
@ -312,18 +312,14 @@ class NativeCall: public NativeInstruction {
|
||||
inline NativeCall* nativeCall_at(address addr) {
|
||||
assert_cond(addr != NULL);
|
||||
NativeCall* call = (NativeCall*)(addr - NativeCall::instruction_offset);
|
||||
#ifdef ASSERT
|
||||
call->verify();
|
||||
#endif
|
||||
DEBUG_ONLY(call->verify());
|
||||
return call;
|
||||
}
|
||||
|
||||
inline NativeCall* nativeCall_before(address return_address) {
|
||||
assert_cond(return_address != NULL);
|
||||
NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
|
||||
#ifdef ASSERT
|
||||
call->verify();
|
||||
#endif
|
||||
DEBUG_ONLY(call->verify());
|
||||
return call;
|
||||
}
|
||||
|
||||
@ -363,7 +359,7 @@ class NativeMovConstReg: public NativeInstruction {
|
||||
}
|
||||
|
||||
intptr_t data() const;
|
||||
void set_data(intptr_t x);
|
||||
void set_data(intptr_t x);
|
||||
|
||||
void flush() {
|
||||
if (!maybe_cpool_ref(instruction_address())) {
|
||||
@ -371,8 +367,8 @@ class NativeMovConstReg: public NativeInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
void verify();
|
||||
void print();
|
||||
void verify();
|
||||
void print();
|
||||
|
||||
// Creation
|
||||
inline friend NativeMovConstReg* nativeMovConstReg_at(address addr);
|
||||
@ -382,55 +378,53 @@ class NativeMovConstReg: public NativeInstruction {
|
||||
inline NativeMovConstReg* nativeMovConstReg_at(address addr) {
|
||||
assert_cond(addr != NULL);
|
||||
NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_offset);
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
DEBUG_ONLY(test->verify());
|
||||
return test;
|
||||
}
|
||||
|
||||
inline NativeMovConstReg* nativeMovConstReg_before(address addr) {
|
||||
assert_cond(addr != NULL);
|
||||
NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
DEBUG_ONLY(test->verify());
|
||||
return test;
|
||||
}
|
||||
|
||||
// RISCV should not use C1 runtime patching, so just leave NativeMovRegMem Unimplemented.
|
||||
// RISCV should not use C1 runtime patching, but still implement
|
||||
// NativeMovRegMem to keep some compilers happy.
|
||||
class NativeMovRegMem: public NativeInstruction {
|
||||
public:
|
||||
int instruction_start() const {
|
||||
Unimplemented();
|
||||
return 0;
|
||||
}
|
||||
enum RISCV_specific_constants {
|
||||
instruction_size = NativeInstruction::instruction_size,
|
||||
instruction_offset = 0,
|
||||
data_offset = 0,
|
||||
next_instruction_offset = NativeInstruction::instruction_size
|
||||
};
|
||||
|
||||
address instruction_address() const {
|
||||
Unimplemented();
|
||||
return NULL;
|
||||
}
|
||||
int instruction_start() const { return instruction_offset; }
|
||||
|
||||
int num_bytes_to_end_of_patch() const {
|
||||
Unimplemented();
|
||||
return 0;
|
||||
}
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
|
||||
int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; }
|
||||
|
||||
int offset() const;
|
||||
|
||||
void set_offset(int x);
|
||||
|
||||
void add_offset_in_bytes(int add_offset) { Unimplemented(); }
|
||||
void add_offset_in_bytes(int add_offset) {
|
||||
set_offset(offset() + add_offset);
|
||||
}
|
||||
|
||||
void verify();
|
||||
void print();
|
||||
|
||||
private:
|
||||
inline friend NativeMovRegMem* nativeMovRegMem_at (address addr);
|
||||
inline friend NativeMovRegMem* nativeMovRegMem_at(address addr);
|
||||
};
|
||||
|
||||
inline NativeMovRegMem* nativeMovRegMem_at (address addr) {
|
||||
Unimplemented();
|
||||
return NULL;
|
||||
inline NativeMovRegMem* nativeMovRegMem_at(address addr) {
|
||||
NativeMovRegMem* test = (NativeMovRegMem*)(addr - NativeMovRegMem::instruction_offset);
|
||||
DEBUG_ONLY(test->verify());
|
||||
return test;
|
||||
}
|
||||
|
||||
class NativeJump: public NativeInstruction {
|
||||
@ -461,9 +455,7 @@ class NativeJump: public NativeInstruction {
|
||||
|
||||
inline NativeJump* nativeJump_at(address addr) {
|
||||
NativeJump* jump = (NativeJump*)(addr - NativeJump::instruction_offset);
|
||||
#ifdef ASSERT
|
||||
jump->verify();
|
||||
#endif
|
||||
DEBUG_ONLY(jump->verify());
|
||||
return jump;
|
||||
}
|
||||
|
||||
|
||||
@ -8936,7 +8936,7 @@ instruct cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST);
|
||||
format %{ "float_b$cmp $op1, $op2 \t#@cmpF_branch"%}
|
||||
format %{ "float_b$cmp $op1, $op2, $lbl \t#@cmpF_branch"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label));
|
||||
@ -8953,7 +8953,7 @@ instruct cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST);
|
||||
format %{ "float_b$cmp $op1, $op2\t#@cmpF_loop"%}
|
||||
format %{ "float_b$cmp $op1, $op2, $lbl\t#@cmpF_loop"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label));
|
||||
@ -8971,7 +8971,7 @@ instruct cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST);
|
||||
format %{ "double_b$cmp $op1, $op2\t#@cmpD_branch"%}
|
||||
format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_branch"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
|
||||
@ -8989,7 +8989,7 @@ instruct cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST);
|
||||
format %{ "double_b$cmp $op1, $op2\t#@cmpD_loop"%}
|
||||
format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_loop"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
|
||||
@ -9264,7 +9264,7 @@ instruct far_cmpFlag_branch(cmpOp cmp, rFlagsReg cr, label lbl) %{
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "far_b$cmp $cr, zr, L\t#@far_cmpFlag_branch"%}
|
||||
format %{ "far_b$cmp $cr, zr, $lbl\t#@far_cmpFlag_branch"%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label), /* is_far */ true);
|
||||
@ -9473,7 +9473,7 @@ instruct far_cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST * 2);
|
||||
format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_branch"%}
|
||||
format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_branch"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
@ -9489,7 +9489,7 @@ instruct far_cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST * 2);
|
||||
format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_loop"%}
|
||||
format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_loop"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
@ -9506,7 +9506,7 @@ instruct far_cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST * 2);
|
||||
format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_branch"%}
|
||||
format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_branch"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
|
||||
@ -9522,7 +9522,7 @@ instruct far_cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
|
||||
effect(USE lbl);
|
||||
|
||||
ins_cost(XFER_COST + BRANCH_COST * 2);
|
||||
format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_loop"%}
|
||||
format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_loop"%}
|
||||
|
||||
ins_encode %{
|
||||
__ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
|
||||
|
||||
@ -119,16 +119,28 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// we don't need to save x6-x7 and x28-x31 which both C and Java treat as
|
||||
// volatile
|
||||
//
|
||||
// we save x18-x27 which Java uses as temporary registers and C
|
||||
// expects to be callee-save
|
||||
// we save x9, x18-x27, f8-f9, and f18-f27 which Java uses as temporary
|
||||
// registers and C expects to be callee-save
|
||||
//
|
||||
// so the stub frame looks like this when we enter Java code
|
||||
//
|
||||
// [ return_from_Java ] <--- sp
|
||||
// [ argument word n ]
|
||||
// ...
|
||||
// -22 [ argument word 1 ]
|
||||
// -21 [ saved x27 ] <--- sp_after_call
|
||||
// -34 [ argument word 1 ]
|
||||
// -33 [ saved f27 ] <--- sp_after_call
|
||||
// -32 [ saved f26 ]
|
||||
// -31 [ saved f25 ]
|
||||
// -30 [ saved f24 ]
|
||||
// -29 [ saved f23 ]
|
||||
// -28 [ saved f22 ]
|
||||
// -27 [ saved f21 ]
|
||||
// -26 [ saved f20 ]
|
||||
// -25 [ saved f19 ]
|
||||
// -24 [ saved f18 ]
|
||||
// -23 [ saved f9 ]
|
||||
// -22 [ saved f8 ]
|
||||
// -21 [ saved x27 ]
|
||||
// -20 [ saved x26 ]
|
||||
// -19 [ saved x25 ]
|
||||
// -18 [ saved x24 ]
|
||||
@ -153,7 +165,20 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
// Call stub stack layout word offsets from fp
|
||||
enum call_stub_layout {
|
||||
sp_after_call_off = -21,
|
||||
sp_after_call_off = -33,
|
||||
|
||||
f27_off = -33,
|
||||
f26_off = -32,
|
||||
f25_off = -31,
|
||||
f24_off = -30,
|
||||
f23_off = -29,
|
||||
f22_off = -28,
|
||||
f21_off = -27,
|
||||
f20_off = -26,
|
||||
f19_off = -25,
|
||||
f18_off = -24,
|
||||
f9_off = -23,
|
||||
f8_off = -22,
|
||||
|
||||
x27_off = -21,
|
||||
x26_off = -20,
|
||||
@ -199,6 +224,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
const Address thread (fp, thread_off * wordSize);
|
||||
|
||||
const Address f27_save (fp, f27_off * wordSize);
|
||||
const Address f26_save (fp, f26_off * wordSize);
|
||||
const Address f25_save (fp, f25_off * wordSize);
|
||||
const Address f24_save (fp, f24_off * wordSize);
|
||||
const Address f23_save (fp, f23_off * wordSize);
|
||||
const Address f22_save (fp, f22_off * wordSize);
|
||||
const Address f21_save (fp, f21_off * wordSize);
|
||||
const Address f20_save (fp, f20_off * wordSize);
|
||||
const Address f19_save (fp, f19_off * wordSize);
|
||||
const Address f18_save (fp, f18_off * wordSize);
|
||||
const Address f9_save (fp, f9_off * wordSize);
|
||||
const Address f8_save (fp, f8_off * wordSize);
|
||||
|
||||
const Address x27_save (fp, x27_off * wordSize);
|
||||
const Address x26_save (fp, x26_off * wordSize);
|
||||
const Address x25_save (fp, x25_off * wordSize);
|
||||
@ -245,6 +283,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ sd(x26, x26_save);
|
||||
__ sd(x27, x27_save);
|
||||
|
||||
__ fsd(f8, f8_save);
|
||||
__ fsd(f9, f9_save);
|
||||
__ fsd(f18, f18_save);
|
||||
__ fsd(f19, f19_save);
|
||||
__ fsd(f20, f20_save);
|
||||
__ fsd(f21, f21_save);
|
||||
__ fsd(f22, f22_save);
|
||||
__ fsd(f23, f23_save);
|
||||
__ fsd(f24, f24_save);
|
||||
__ fsd(f25, f25_save);
|
||||
__ fsd(f26, f26_save);
|
||||
__ fsd(f27, f27_save);
|
||||
|
||||
// install Java thread in global register now we have saved
|
||||
// whatever value it held
|
||||
__ mv(xthread, c_rarg7);
|
||||
@ -336,6 +387,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#endif
|
||||
|
||||
// restore callee-save registers
|
||||
__ fld(f27, f27_save);
|
||||
__ fld(f26, f26_save);
|
||||
__ fld(f25, f25_save);
|
||||
__ fld(f24, f24_save);
|
||||
__ fld(f23, f23_save);
|
||||
__ fld(f22, f22_save);
|
||||
__ fld(f21, f21_save);
|
||||
__ fld(f20, f20_save);
|
||||
__ fld(f19, f19_save);
|
||||
__ fld(f18, f18_save);
|
||||
__ fld(f9, f9_save);
|
||||
__ fld(f8, f8_save);
|
||||
|
||||
__ ld(x27, x27_save);
|
||||
__ ld(x26, x26_save);
|
||||
__ ld(x25, x25_save);
|
||||
|
||||
@ -40,7 +40,7 @@ void VMRegImpl::set_regName() {
|
||||
FloatRegister freg = ::as_FloatRegister(0);
|
||||
for ( ; i < ConcreteRegisterImpl::max_fpr ; ) {
|
||||
for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) {
|
||||
regName[i++] = reg->name();
|
||||
regName[i++] = freg->name();
|
||||
}
|
||||
freg = freg->successor();
|
||||
}
|
||||
@ -48,7 +48,7 @@ void VMRegImpl::set_regName() {
|
||||
VectorRegister vreg = ::as_VectorRegister(0);
|
||||
for ( ; i < ConcreteRegisterImpl::max_vpr ; ) {
|
||||
for (int j = 0 ; j < VectorRegisterImpl::max_slots_per_register ; j++) {
|
||||
regName[i++] = reg->name();
|
||||
regName[i++] = vreg->name();
|
||||
}
|
||||
vreg = vreg->successor();
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
|
||||
|
||||
// Entry arguments:
|
||||
// t2: CompiledICHolder
|
||||
// t1: CompiledICHolder
|
||||
// j_rarg0: Receiver
|
||||
|
||||
// This stub is called from compiled code which has no callee-saved registers,
|
||||
|
||||
@ -1125,7 +1125,7 @@ void InterpreterMacroAssembler::remove_activation(
|
||||
|
||||
bind(loop);
|
||||
// check if current entry is used
|
||||
cmpptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL);
|
||||
cmpptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD);
|
||||
jcc(Assembler::notEqual, exception);
|
||||
|
||||
addptr(rmon, entry_size); // otherwise advance to next entry
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -348,10 +348,10 @@ class SlowSignatureHandler
|
||||
intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0));
|
||||
_from -= Interpreter::stackElementSize;
|
||||
if (_num_args < Argument::n_int_register_parameters_c-1) {
|
||||
*_reg_args++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr;
|
||||
*_reg_args++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr;
|
||||
_num_args++;
|
||||
} else {
|
||||
*_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr;
|
||||
*_to++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,10 +443,10 @@ class SlowSignatureHandler
|
||||
_from -= Interpreter::stackElementSize;
|
||||
|
||||
if (_num_int_args < Argument::n_int_register_parameters_c-1) {
|
||||
*_int_args++ = (*from_addr == 0) ? NULL : (intptr_t)from_addr;
|
||||
*_int_args++ = (*from_addr == 0) ? NULL_WORD : (intptr_t)from_addr;
|
||||
_num_int_args++;
|
||||
} else {
|
||||
*_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr;
|
||||
*_to++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -529,7 +529,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// make sure this code is only executed if there is a pending exception
|
||||
{
|
||||
Label L;
|
||||
__ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL);
|
||||
__ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL_WORD);
|
||||
__ jcc(Assembler::notEqual, L);
|
||||
__ stop("StubRoutines::forward exception: no pending exception (1)");
|
||||
__ bind(L);
|
||||
|
||||
@ -790,7 +790,7 @@ void Canonicalizer::do_If(If* x) {
|
||||
else if (lss_sux == gtr_sux) { cond = If::neq; tsux = lss_sux; fsux = eql_sux; }
|
||||
else if (eql_sux == gtr_sux) { cond = If::geq; tsux = eql_sux; fsux = lss_sux; }
|
||||
else { ShouldNotReachHere(); }
|
||||
If* canon = new If(cmp->x(), cond, nan_sux == tsux, cmp->y(), tsux, fsux, cmp->state_before(), x->is_safepoint());
|
||||
If* canon = new If(cmp->x(), cond, nan_sux == tsux, cmp->y(), tsux, fsux, x->state_before(), x->is_safepoint());
|
||||
if (cmp->x() == cmp->y()) {
|
||||
do_If(canon);
|
||||
} else {
|
||||
|
||||
@ -2232,8 +2232,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
|
||||
void GraphBuilder::new_instance(int klass_index) {
|
||||
ValueStack* state_before = copy_state_exhandling();
|
||||
bool will_link;
|
||||
ciKlass* klass = stream()->get_klass(will_link);
|
||||
ciKlass* klass = stream()->get_klass();
|
||||
assert(klass->is_instance_klass(), "must be an instance klass");
|
||||
NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before, stream()->is_unresolved_klass());
|
||||
_memory->new_instance(new_instance);
|
||||
@ -2248,8 +2247,7 @@ void GraphBuilder::new_type_array() {
|
||||
|
||||
|
||||
void GraphBuilder::new_object_array() {
|
||||
bool will_link;
|
||||
ciKlass* klass = stream()->get_klass(will_link);
|
||||
ciKlass* klass = stream()->get_klass();
|
||||
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
|
||||
NewArray* n = new NewObjectArray(klass, ipop(), state_before);
|
||||
apush(append_split(n));
|
||||
@ -2274,8 +2272,7 @@ bool GraphBuilder::direct_compare(ciKlass* k) {
|
||||
|
||||
|
||||
void GraphBuilder::check_cast(int klass_index) {
|
||||
bool will_link;
|
||||
ciKlass* klass = stream()->get_klass(will_link);
|
||||
ciKlass* klass = stream()->get_klass();
|
||||
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_for_exception();
|
||||
CheckCast* c = new CheckCast(klass, apop(), state_before);
|
||||
apush(append_split(c));
|
||||
@ -2295,8 +2292,7 @@ void GraphBuilder::check_cast(int klass_index) {
|
||||
|
||||
|
||||
void GraphBuilder::instance_of(int klass_index) {
|
||||
bool will_link;
|
||||
ciKlass* klass = stream()->get_klass(will_link);
|
||||
ciKlass* klass = stream()->get_klass();
|
||||
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
|
||||
InstanceOf* i = new InstanceOf(klass, apop(), state_before);
|
||||
ipush(append_split(i));
|
||||
@ -2331,8 +2327,7 @@ void GraphBuilder::monitorexit(Value x, int bci) {
|
||||
|
||||
|
||||
void GraphBuilder::new_multi_array(int dimensions) {
|
||||
bool will_link;
|
||||
ciKlass* klass = stream()->get_klass(will_link);
|
||||
ciKlass* klass = stream()->get_klass();
|
||||
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
|
||||
|
||||
Values* dims = new Values(dimensions, dimensions, NULL);
|
||||
|
||||
@ -1260,6 +1260,37 @@ JRT_END
|
||||
|
||||
#else // DEOPTIMIZE_WHEN_PATCHING
|
||||
|
||||
static bool is_patching_needed(JavaThread* current, Runtime1::StubID stub_id) {
|
||||
if (stub_id == Runtime1::load_klass_patching_id ||
|
||||
stub_id == Runtime1::load_mirror_patching_id) {
|
||||
// last java frame on stack
|
||||
vframeStream vfst(current, true);
|
||||
assert(!vfst.at_end(), "Java frame must exist");
|
||||
|
||||
methodHandle caller_method(current, vfst.method());
|
||||
int bci = vfst.bci();
|
||||
Bytecodes::Code code = caller_method()->java_code_at(bci);
|
||||
|
||||
switch (code) {
|
||||
case Bytecodes::_new:
|
||||
case Bytecodes::_anewarray:
|
||||
case Bytecodes::_multianewarray:
|
||||
case Bytecodes::_instanceof:
|
||||
case Bytecodes::_checkcast: {
|
||||
Bytecode bc(caller_method(), caller_method->bcp_from(bci));
|
||||
constantTag tag = caller_method->constants()->tag_at(bc.get_index_u2(code));
|
||||
if (tag.is_unresolved_klass_in_error()) {
|
||||
return false; // throws resolution error
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id) {
|
||||
#ifndef PRODUCT
|
||||
if (PrintC1Statistics) {
|
||||
@ -1281,10 +1312,12 @@ void Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_id) {
|
||||
frame caller_frame = runtime_frame.sender(®_map);
|
||||
assert(caller_frame.is_compiled_frame(), "Wrong frame type");
|
||||
|
||||
// Make sure the nmethod is invalidated, i.e. made not entrant.
|
||||
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
|
||||
if (nm != NULL) {
|
||||
nm->make_not_entrant();
|
||||
if (is_patching_needed(current, stub_id)) {
|
||||
// Make sure the nmethod is invalidated, i.e. made not entrant.
|
||||
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
|
||||
if (nm != NULL) {
|
||||
nm->make_not_entrant();
|
||||
}
|
||||
}
|
||||
|
||||
Deoptimization::deoptimize_frame(current, caller_frame.id());
|
||||
|
||||
@ -23,9 +23,10 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "ci/ciCallSite.hpp"
|
||||
#include "ci/ciConstant.hpp"
|
||||
#include "ci/ciField.hpp"
|
||||
#include "ci/ciKlass.hpp"
|
||||
#include "ci/ciObjArrayKlass.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "ci/ciSymbols.hpp"
|
||||
#include "ci/ciUtilities.inline.hpp"
|
||||
@ -191,6 +192,25 @@ ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
|
||||
return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder);
|
||||
}
|
||||
|
||||
// ciBytecodeStream::get_klass
|
||||
//
|
||||
// If this bytecode is a new, newarray, multianewarray, instanceof,
|
||||
// or checkcast, get the referenced klass. Retuns an unloaded ciKlass
|
||||
// if the referenced klass is not accessible.
|
||||
ciKlass* ciBytecodeStream::get_klass() {
|
||||
bool will_link;
|
||||
ciKlass* klass = get_klass(will_link);
|
||||
if (!will_link && klass->is_loaded()) { // klass not accessible
|
||||
if (klass->is_array_klass()) {
|
||||
assert(!klass->is_type_array_klass(), "");
|
||||
klass = ciEnv::unloaded_ciobjarrayklass();
|
||||
} else {
|
||||
klass = ciEnv::unloaded_ciinstance_klass();
|
||||
}
|
||||
}
|
||||
return klass;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciBytecodeStream::get_constant_raw_index
|
||||
//
|
||||
|
||||
@ -219,6 +219,7 @@ public:
|
||||
|
||||
// If this bytecode is a new, newarray, multianewarray, instanceof,
|
||||
// or checkcast, get the referenced klass.
|
||||
ciKlass* get_klass();
|
||||
ciKlass* get_klass(bool& will_link);
|
||||
int get_klass_index() const;
|
||||
|
||||
|
||||
@ -205,7 +205,7 @@ inline oop ShenandoahBarrierSet::oop_cmpxchg(DecoratorSet decorators, T* addr, o
|
||||
|
||||
// Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
|
||||
// because it must be the previous value.
|
||||
res = load_reference_barrier(decorators, res, reinterpret_cast<T*>(NULL));
|
||||
res = load_reference_barrier(decorators, res, static_cast<T*>(nullptr));
|
||||
satb_enqueue(res);
|
||||
return res;
|
||||
}
|
||||
@ -216,7 +216,7 @@ inline oop ShenandoahBarrierSet::oop_xchg(DecoratorSet decorators, T* addr, oop
|
||||
oop previous = RawAccess<>::oop_atomic_xchg(addr, new_value);
|
||||
// Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
|
||||
// because it must be the previous value.
|
||||
previous = load_reference_barrier<T>(decorators, previous, reinterpret_cast<T*>(NULL));
|
||||
previous = load_reference_barrier<T>(decorators, previous, static_cast<T*>(nullptr));
|
||||
satb_enqueue(previous);
|
||||
return previous;
|
||||
}
|
||||
|
||||
@ -77,9 +77,11 @@ class Bytecode: public StackObj {
|
||||
int get_index_u2(Bytecodes::Code bc, bool is_wide = false) const {
|
||||
assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide);
|
||||
address p = addr_at(is_wide ? 2 : 1);
|
||||
if (can_use_native_byte_order(bc, is_wide))
|
||||
if (can_use_native_byte_order(bc, is_wide)) {
|
||||
return Bytes::get_native_u2(p);
|
||||
else return Bytes::get_Java_u2(p);
|
||||
} else {
|
||||
return Bytes::get_Java_u2(p);
|
||||
}
|
||||
}
|
||||
int get_index_u1_cpcache(Bytecodes::Code bc) const {
|
||||
assert_same_format_as(bc); assert_index_size(1, bc);
|
||||
|
||||
@ -294,8 +294,8 @@ public:
|
||||
static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
|
||||
arrayOop dst_obj, size_t dst_offset_in_bytes,
|
||||
size_t length) {
|
||||
AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const T*>(NULL),
|
||||
dst_obj, dst_offset_in_bytes, reinterpret_cast<T*>(NULL),
|
||||
AccessT::arraycopy(src_obj, src_offset_in_bytes, static_cast<const T*>(nullptr),
|
||||
dst_obj, dst_offset_in_bytes, static_cast<T*>(nullptr),
|
||||
length);
|
||||
}
|
||||
|
||||
@ -303,7 +303,7 @@ public:
|
||||
static inline void arraycopy_to_native(arrayOop src_obj, size_t src_offset_in_bytes,
|
||||
T* dst,
|
||||
size_t length) {
|
||||
AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const T*>(NULL),
|
||||
AccessT::arraycopy(src_obj, src_offset_in_bytes, static_cast<const T*>(nullptr),
|
||||
NULL, 0, dst,
|
||||
length);
|
||||
}
|
||||
@ -313,15 +313,15 @@ public:
|
||||
arrayOop dst_obj, size_t dst_offset_in_bytes,
|
||||
size_t length) {
|
||||
AccessT::arraycopy(NULL, 0, src,
|
||||
dst_obj, dst_offset_in_bytes, reinterpret_cast<T*>(NULL),
|
||||
dst_obj, dst_offset_in_bytes, static_cast<T*>(nullptr),
|
||||
length);
|
||||
}
|
||||
|
||||
static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
|
||||
arrayOop dst_obj, size_t dst_offset_in_bytes,
|
||||
size_t length) {
|
||||
return AccessT::oop_arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const HeapWord*>(NULL),
|
||||
dst_obj, dst_offset_in_bytes, reinterpret_cast<HeapWord*>(NULL),
|
||||
return AccessT::oop_arraycopy(src_obj, src_offset_in_bytes, static_cast<const HeapWord*>(nullptr),
|
||||
dst_obj, dst_offset_in_bytes, static_cast<HeapWord*>(nullptr),
|
||||
length);
|
||||
}
|
||||
|
||||
|
||||
@ -1648,13 +1648,16 @@ Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTran
|
||||
"narrow type must be narrower than length type");
|
||||
|
||||
// Return NULL if new nodes are not allowed
|
||||
if (!allow_new_nodes) return NULL;
|
||||
if (!allow_new_nodes) {
|
||||
return NULL;
|
||||
}
|
||||
// Create a cast which is control dependent on the initialization to
|
||||
// propagate the fact that the array length must be positive.
|
||||
InitializeNode* init = initialization();
|
||||
assert(init != NULL, "initialization not found");
|
||||
length = new CastIINode(length, narrow_length_type);
|
||||
length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control));
|
||||
if (init != NULL) {
|
||||
length = new CastIINode(length, narrow_length_type);
|
||||
length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1383,7 +1383,8 @@ void PhaseIdealLoop::copy_skeleton_predicates_to_main_loop_helper(Node* predicat
|
||||
}
|
||||
}
|
||||
|
||||
static bool skeleton_follow_inputs(Node* n, int op) {
|
||||
static bool skeleton_follow_inputs(Node* n) {
|
||||
int op = n->Opcode();
|
||||
return (n->is_Bool() ||
|
||||
n->is_Cmp() ||
|
||||
op == Op_AndL ||
|
||||
@ -1401,31 +1402,27 @@ static bool skeleton_follow_inputs(Node* n, int op) {
|
||||
op == Op_CastII);
|
||||
}
|
||||
|
||||
bool PhaseIdealLoop::subgraph_has_opaque(Node* n) {
|
||||
if (n->Opcode() == Op_OpaqueLoopInit || n->Opcode() == Op_OpaqueLoopStride) {
|
||||
return true;
|
||||
}
|
||||
if (!skeleton_follow_inputs(n)) {
|
||||
return false;
|
||||
}
|
||||
uint init;
|
||||
uint stride;
|
||||
count_opaque_loop_nodes(n, init, stride);
|
||||
return init != 0 || stride != 0;
|
||||
}
|
||||
|
||||
|
||||
bool PhaseIdealLoop::skeleton_predicate_has_opaque(IfNode* iff) {
|
||||
uint init;
|
||||
uint stride;
|
||||
count_opaque_loop_nodes(iff->in(1)->in(1), init, stride);
|
||||
#ifdef ASSERT
|
||||
ResourceMark rm;
|
||||
Unique_Node_List wq;
|
||||
wq.push(iff->in(1)->in(1));
|
||||
uint init = 0;
|
||||
uint stride = 0;
|
||||
for (uint i = 0; i < wq.size(); i++) {
|
||||
Node* n = wq.at(i);
|
||||
int op = n->Opcode();
|
||||
if (skeleton_follow_inputs(n, op)) {
|
||||
for (uint j = 1; j < n->req(); j++) {
|
||||
Node* m = n->in(j);
|
||||
if (m != NULL) {
|
||||
wq.push(m);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (n->Opcode() == Op_OpaqueLoopInit) {
|
||||
init++;
|
||||
} else if (n->Opcode() == Op_OpaqueLoopStride) {
|
||||
stride++;
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
wq.clear();
|
||||
wq.push(iff->in(1)->in(1));
|
||||
uint verif_init = 0;
|
||||
@ -1454,6 +1451,31 @@ bool PhaseIdealLoop::skeleton_predicate_has_opaque(IfNode* iff) {
|
||||
return init != 0;
|
||||
}
|
||||
|
||||
void PhaseIdealLoop::count_opaque_loop_nodes(Node* n, uint& init, uint& stride) {
|
||||
init = 0;
|
||||
stride = 0;
|
||||
ResourceMark rm;
|
||||
Unique_Node_List wq;
|
||||
wq.push(n);
|
||||
for (uint i = 0; i < wq.size(); i++) {
|
||||
Node* n = wq.at(i);
|
||||
if (skeleton_follow_inputs(n)) {
|
||||
for (uint j = 1; j < n->req(); j++) {
|
||||
Node* m = n->in(j);
|
||||
if (m != NULL) {
|
||||
wq.push(m);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (n->Opcode() == Op_OpaqueLoopInit) {
|
||||
init++;
|
||||
} else if (n->Opcode() == Op_OpaqueLoopStride) {
|
||||
stride++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the skeleton predicate bool for a main or unswitched loop:
|
||||
// Main loop: Set new_init and new_stride nodes as new inputs.
|
||||
// Unswitched loop: new_init and new_stride are both NULL. Clone OpaqueLoopInit and OpaqueLoopStride instead.
|
||||
@ -1473,8 +1495,7 @@ Node* PhaseIdealLoop::clone_skeleton_predicate_bool(Node* iff, Node* new_init, N
|
||||
Node* n = to_clone.node();
|
||||
uint i = to_clone.index();
|
||||
Node* m = n->in(i);
|
||||
int op = m->Opcode();
|
||||
if (skeleton_follow_inputs(m, op)) {
|
||||
if (skeleton_follow_inputs(m)) {
|
||||
to_clone.push(m, 1);
|
||||
continue;
|
||||
}
|
||||
@ -1483,6 +1504,7 @@ Node* PhaseIdealLoop::clone_skeleton_predicate_bool(Node* iff, Node* new_init, N
|
||||
n = n->clone();
|
||||
register_new_node(n, control);
|
||||
}
|
||||
int op = m->Opcode();
|
||||
if (op == Op_OpaqueLoopInit) {
|
||||
if (is_unswitched_loop && m->_idx < current && new_init == NULL) {
|
||||
new_init = m->clone();
|
||||
|
||||
@ -931,6 +931,8 @@ private:
|
||||
IdealLoopTree* outer_loop, Node* input_proj);
|
||||
Node* clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* control);
|
||||
static bool skeleton_predicate_has_opaque(IfNode* iff);
|
||||
static void count_opaque_loop_nodes(Node* n, uint& init, uint& stride);
|
||||
static bool subgraph_has_opaque(Node* n);
|
||||
static void get_skeleton_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false);
|
||||
void update_main_loop_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con);
|
||||
void copy_skeleton_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* init, Node* stride);
|
||||
|
||||
@ -2155,11 +2155,18 @@ static void clone_outer_loop_helper(Node* n, const IdealLoopTree *loop, const Id
|
||||
Node* c = phase->get_ctrl(u);
|
||||
IdealLoopTree* u_loop = phase->get_loop(c);
|
||||
assert(!loop->is_member(u_loop), "can be in outer loop or out of both loops only");
|
||||
if (outer_loop->is_member(u_loop) ||
|
||||
// nodes pinned with control in the outer loop but not referenced from the safepoint must be moved out of
|
||||
// the outer loop too
|
||||
(u->in(0) != NULL && outer_loop->is_member(phase->get_loop(u->in(0))))) {
|
||||
if (outer_loop->is_member(u_loop)) {
|
||||
wq.push(u);
|
||||
} else {
|
||||
// nodes pinned with control in the outer loop but not referenced from the safepoint must be moved out of
|
||||
// the outer loop too
|
||||
Node* u_c = u->in(0);
|
||||
if (u_c != NULL) {
|
||||
IdealLoopTree* u_c_loop = phase->get_loop(u_c);
|
||||
if (outer_loop->is_member(u_c_loop) && !loop->is_member(u_c_loop)) {
|
||||
wq.push(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1773,6 +1773,10 @@ void PhaseCCP::analyze() {
|
||||
} else {
|
||||
n = worklist.pop();
|
||||
}
|
||||
if (n->is_SafePoint()) {
|
||||
// Keep track of SafePoint nodes for PhaseCCP::transform()
|
||||
_safepoints.push(n);
|
||||
}
|
||||
const Type *t = n->Value(this);
|
||||
if (t != type(n)) {
|
||||
assert(ccp_type_widens(t, type(n)), "ccp type must widen");
|
||||
@ -1907,6 +1911,23 @@ Node *PhaseCCP::transform( Node *n ) {
|
||||
GrowableArray <Node *> trstack(C->live_nodes() >> 1);
|
||||
|
||||
trstack.push(new_node); // Process children of cloned node
|
||||
|
||||
// This CCP pass may prove that no exit test for a loop ever succeeds (i.e. the loop is infinite). In that case,
|
||||
// the logic below doesn't follow any path from Root to the loop body: there's at least one such path but it's proven
|
||||
// never taken (its type is TOP). As a consequence the node on the exit path that's input to Root (let's call it n) is
|
||||
// replaced by the top node and the inputs of that node n are not enqueued for further processing. If CCP only works
|
||||
// through the graph from Root, this causes the loop body to never be processed here even when it's not dead (that
|
||||
// is reachable from Root following its uses). To prevent that issue, transform() starts walking the graph from Root
|
||||
// and all safepoints.
|
||||
for (uint i = 0; i < _safepoints.size(); ++i) {
|
||||
Node* nn = _safepoints.at(i);
|
||||
Node* new_node = _nodes[nn->_idx];
|
||||
assert(new_node == NULL, "");
|
||||
new_node = transform_once(nn);
|
||||
_nodes.map(nn->_idx, new_node);
|
||||
trstack.push(new_node);
|
||||
}
|
||||
|
||||
while ( trstack.is_nonempty() ) {
|
||||
Node *clone = trstack.pop();
|
||||
uint cnt = clone->req();
|
||||
|
||||
@ -565,6 +565,7 @@ protected:
|
||||
// Phase for performing global Conditional Constant Propagation.
|
||||
// Should be replaced with combined CCP & GVN someday.
|
||||
class PhaseCCP : public PhaseIterGVN {
|
||||
Unique_Node_List _safepoints;
|
||||
// Non-recursive. Use analysis to transform single Node.
|
||||
virtual Node *transform_once( Node *n );
|
||||
|
||||
|
||||
@ -200,7 +200,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (n->Opcode() == Op_OpaqueLoopStride || n->Opcode() == Op_OpaqueLoopInit) {
|
||||
if (subgraph_has_opaque(n)) {
|
||||
Unique_Node_List wq;
|
||||
wq.push(n);
|
||||
for (uint i = 0; i < wq.size(); i++) {
|
||||
|
||||
@ -261,10 +261,12 @@ void StringConcat::eliminate_unneeded_control() {
|
||||
Node* cmp = bol->in(1);
|
||||
assert(cmp->is_Cmp(), "unexpected if shape");
|
||||
if (cmp->in(1)->is_top() || cmp->in(2)->is_top()) {
|
||||
// This region should lose its Phis and be optimized out by igvn but there's a chance the if folds to top first
|
||||
// which then causes a reachable part of the graph to become dead.
|
||||
// This region should lose its Phis. They are removed either in PhaseRemoveUseless (for data phis) or in IGVN
|
||||
// (for memory phis). During IGVN, there is a chance that the If folds to top before the Region is processed
|
||||
// which then causes a reachable part of the graph to become dead. To prevent this, set the boolean input of
|
||||
// the If to a constant to nicely let the diamond Region/If fold away.
|
||||
Compile* C = _stringopts->C;
|
||||
C->gvn_replace_by(n, iff->in(0));
|
||||
C->gvn_replace_by(iff->in(1), _stringopts->gvn()->intcon(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1022,6 +1024,21 @@ bool StringConcat::validate_control_flow() {
|
||||
fail = true;
|
||||
break;
|
||||
} else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) {
|
||||
// Check for side effect between Initialize and the constructor
|
||||
for (SimpleDUIterator iter(ptr); iter.has_next(); iter.next()) {
|
||||
Node* use = iter.get();
|
||||
if (!use->is_CFG() && !use->is_CheckCastPP() && !use->is_Load()) {
|
||||
#ifndef PRODUCT
|
||||
if (PrintOptimizeStringConcat) {
|
||||
tty->print_cr("unexpected control use of Initialize");
|
||||
ptr->in(0)->dump(); // Initialize node
|
||||
use->dump(1);
|
||||
}
|
||||
#endif
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = ptr->in(0)->in(0);
|
||||
} else if (ptr->is_Region()) {
|
||||
Node* copy = ptr->as_Region()->is_copy();
|
||||
|
||||
@ -1615,14 +1615,15 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
// Change x u< 1 or x u<= 0 to x == 0
|
||||
// and x u> 0 or u>= 1 to x != 0
|
||||
if (cop == Op_CmpU &&
|
||||
cmp1_op != Op_LoadRange &&
|
||||
((_test._test == BoolTest::lt &&
|
||||
(((_test._test == BoolTest::lt || _test._test == BoolTest::ge) &&
|
||||
cmp2->find_int_con(-1) == 1) ||
|
||||
(_test._test == BoolTest::le &&
|
||||
((_test._test == BoolTest::le || _test._test == BoolTest::gt) &&
|
||||
cmp2->find_int_con(-1) == 0))) {
|
||||
Node* ncmp = phase->transform(new CmpINode(cmp1, phase->intcon(0)));
|
||||
return new BoolNode(ncmp, BoolTest::eq);
|
||||
return new BoolNode(ncmp, _test.is_less() ? BoolTest::eq : BoolTest::ne);
|
||||
}
|
||||
|
||||
// Change (arraylength <= 0) or (arraylength == 0)
|
||||
|
||||
@ -668,7 +668,7 @@ const char* ObjectMonitor::is_busy_to_string(stringStream* ss) {
|
||||
} else {
|
||||
// We report NULL instead of DEFLATER_MARKER here because is_busy()
|
||||
// ignores DEFLATER_MARKER values.
|
||||
ss->print("owner=" INTPTR_FORMAT, NULL);
|
||||
ss->print("owner=" INTPTR_FORMAT, NULL_WORD);
|
||||
}
|
||||
ss->print(", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, p2i(_cxq),
|
||||
p2i(_EntryList));
|
||||
|
||||
@ -69,7 +69,10 @@
|
||||
|
||||
#endif // clang/gcc version check
|
||||
|
||||
#if (__GNUC__ >= 10) || (defined(__clang_major__) && (__clang_major__ >= 14))
|
||||
#if (__GNUC__ >= 10)
|
||||
// TODO: Re-enable warning attribute for Clang once
|
||||
// https://github.com/llvm/llvm-project/issues/56519 is fixed and released.
|
||||
// || (defined(__clang_major__) && (__clang_major__ >= 14))
|
||||
|
||||
// Use "warning" attribute to detect uses of "forbidden" functions.
|
||||
//
|
||||
@ -92,6 +95,6 @@
|
||||
__VA_ARGS__ \
|
||||
PRAGMA_DIAG_POP
|
||||
|
||||
#endif // gcc10+ or clang14+
|
||||
#endif // gcc10+
|
||||
|
||||
#endif // SHARE_UTILITIES_COMPILERWARNINGS_GCC_HPP
|
||||
|
||||
@ -1815,9 +1815,9 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* returning source id or retry indicator.
|
||||
*
|
||||
* @param w caller's WorkQueue
|
||||
* @param prevSrc the previous queue stolen from in current phase, or 0
|
||||
* @param prevSrc the two previous queues (if nonzero) stolen from in current phase, packed as int
|
||||
* @param r random seed
|
||||
* @return id of queue if taken, negative if none found, prevSrc for retry
|
||||
* @return the next prevSrc value to use, or negative if none found
|
||||
*/
|
||||
private int scan(WorkQueue w, int prevSrc, int r) {
|
||||
WorkQueue[] qs = queues;
|
||||
@ -1835,10 +1835,11 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
else if (t != null && WorkQueue.casSlotToNull(a, k, t)) {
|
||||
q.base = nb;
|
||||
w.source = src;
|
||||
if (prevSrc == 0 && q.base == nb && a[nk] != null)
|
||||
signalWork(); // propagate
|
||||
if (src + (src << SWIDTH) != prevSrc &&
|
||||
q.base == nb && a[nk] != null)
|
||||
signalWork(); // propagate at most twice/run
|
||||
w.topLevelExec(t, q);
|
||||
return src;
|
||||
return src + (prevSrc << SWIDTH);
|
||||
}
|
||||
else if (q.array != a || a[k] != null || a[nk] != null)
|
||||
return prevSrc; // revisit
|
||||
|
||||
@ -582,12 +582,8 @@ public final class ZoneInfoFile {
|
||||
// we can then pass in the dom = -1, dow > 0 into ZoneInfo
|
||||
//
|
||||
// hacking, assume the >=24 is the result of ZRB optimization for
|
||||
// "last", it works for now. From tzdata2020d this hacking
|
||||
// will not work for Asia/Gaza and Asia/Hebron which follow
|
||||
// Palestine DST rules.
|
||||
if (dom < 0 || dom >= 24 &&
|
||||
!(zoneId.equals("Asia/Gaza") ||
|
||||
zoneId.equals("Asia/Hebron"))) {
|
||||
// "last", it works for now.
|
||||
if (dom < 0 || dom >= 24) {
|
||||
params[1] = -1;
|
||||
params[2] = toCalendarDOW[dow];
|
||||
} else {
|
||||
@ -609,7 +605,6 @@ public final class ZoneInfoFile {
|
||||
params[7] = 0;
|
||||
} else {
|
||||
// hacking: see comment above
|
||||
// No need of hacking for Asia/Gaza and Asia/Hebron from tz2021e
|
||||
if (dom < 0 || dom >= 24) {
|
||||
params[6] = -1;
|
||||
params[7] = toCalendarDOW[dow];
|
||||
|
||||
@ -21,4 +21,4 @@
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
tzdata2022c
|
||||
tzdata2022d
|
||||
|
||||
@ -3398,10 +3398,6 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
|
||||
# The winter time in 2015 started on October 23 at 01:00.
|
||||
# https://wafa.ps/ar_page.aspx?id=CgpCdYa670694628582aCgpCdY
|
||||
# http://www.palestinecabinet.gov.ps/portal/meeting/details/27583
|
||||
#
|
||||
# From Paul Eggert (2019-04-10):
|
||||
# For now, guess spring-ahead transitions are at 00:00 on the Saturday
|
||||
# preceding March's last Sunday (i.e., Sat>=24).
|
||||
|
||||
# From P Chan (2021-10-18):
|
||||
# http://wafa.ps/Pages/Details/34701
|
||||
@ -3418,6 +3414,18 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
|
||||
# From Heba Hamad (2022-03-10):
|
||||
# summer time will begin in Palestine from Sunday 03-27-2022, 00:00 AM.
|
||||
|
||||
# From Heba Hamad (2022-08-30):
|
||||
# winter time will begin in Palestine from Saturday 10-29, 02:00 AM by
|
||||
# 60 minutes backwards. Also the state of Palestine adopted the summer
|
||||
# and winter time for the years: 2023,2024,2025,2026 ...
|
||||
# https://mm.icann.org/pipermail/tz/attachments/20220830/9f024566/Time-0001.pdf
|
||||
# (2022-08-31): ... the Saturday before the last Sunday in March and October
|
||||
# at 2:00 AM ,for the years from 2023 to 2026.
|
||||
# (2022-09-05): https://mtit.pna.ps/Site/New/1453
|
||||
#
|
||||
# From Paul Eggert (2022-08-31):
|
||||
# For now, assume that this rule will also be used after 2026.
|
||||
|
||||
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
|
||||
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
|
||||
Rule EgyptAsia 1957 1958 - Oct 1 0:00 0 -
|
||||
@ -3448,14 +3456,16 @@ Rule Palestine 2013 only - Sep 27 0:00 0 -
|
||||
Rule Palestine 2014 only - Oct 24 0:00 0 -
|
||||
Rule Palestine 2015 only - Mar 28 0:00 1:00 S
|
||||
Rule Palestine 2015 only - Oct 23 1:00 0 -
|
||||
Rule Palestine 2016 2018 - Mar Sat>=24 1:00 1:00 S
|
||||
Rule Palestine 2016 2018 - Oct Sat>=24 1:00 0 -
|
||||
Rule Palestine 2016 2018 - Mar Sat<=30 1:00 1:00 S
|
||||
Rule Palestine 2016 2018 - Oct Sat<=30 1:00 0 -
|
||||
Rule Palestine 2019 only - Mar 29 0:00 1:00 S
|
||||
Rule Palestine 2019 only - Oct Sat>=24 0:00 0 -
|
||||
Rule Palestine 2020 2021 - Mar Sat>=24 0:00 1:00 S
|
||||
Rule Palestine 2019 only - Oct Sat<=30 0:00 0 -
|
||||
Rule Palestine 2020 2021 - Mar Sat<=30 0:00 1:00 S
|
||||
Rule Palestine 2020 only - Oct 24 1:00 0 -
|
||||
Rule Palestine 2021 max - Oct Fri>=23 1:00 0 -
|
||||
Rule Palestine 2022 max - Mar Sun>=25 0:00 1:00 S
|
||||
Rule Palestine 2021 only - Oct 29 1:00 0 -
|
||||
Rule Palestine 2022 only - Mar 27 0:00 1:00 S
|
||||
Rule Palestine 2022 max - Oct Sat<=30 2:00 0 -
|
||||
Rule Palestine 2023 max - Mar Sat<=30 2:00 1:00 S
|
||||
|
||||
# Zone NAME STDOFF RULES FORMAT [UNTIL]
|
||||
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
|
||||
|
||||
@ -113,6 +113,8 @@ Link Etc/UTC Etc/UCT
|
||||
Link Europe/London Europe/Belfast
|
||||
Link Europe/Kyiv Europe/Kiev
|
||||
Link Europe/Chisinau Europe/Tiraspol
|
||||
Link Europe/Kyiv Europe/Uzhgorod
|
||||
Link Europe/Kyiv Europe/Zaporozhye
|
||||
Link Europe/London GB
|
||||
Link Europe/London GB-Eire
|
||||
Link Etc/GMT GMT+0
|
||||
|
||||
@ -2638,10 +2638,14 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880
|
||||
# From Alexander Krivenyshev (2014-03-17):
|
||||
# time change at 2:00 (2am) on March 30, 2014
|
||||
# https://vz.ru/news/2014/3/17/677464.html
|
||||
# From Paul Eggert (2014-03-30):
|
||||
# Simferopol and Sevastopol reportedly changed their central town clocks
|
||||
# late the previous day, but this appears to have been ceremonial
|
||||
# and the discrepancies are small enough to not worry about.
|
||||
# From Tim Parenti (2022-07-01), per Paul Eggert (2014-03-30):
|
||||
# The clocks at the railway station in Simferopol were put forward from 22:00
|
||||
# to 24:00 the previous day in a "symbolic ceremony"; however, per
|
||||
# contemporaneous news reports, "ordinary Crimeans [made] the daylight savings
|
||||
# time switch at 2am" on Sunday.
|
||||
# https://www.business-standard.com/article/pti-stories/crimea-to-set-clocks-to-russia-time-114033000014_1.html
|
||||
# https://www.reuters.com/article/us-ukraine-crisis-crimea-time/crimea-switches-to-moscow-time-amid-incorporation-frenzy-idUKBREA2S0LT20140329
|
||||
# https://www.bbc.com/news/av/world-europe-26806583
|
||||
2:00 EU EE%sT 2014 Mar 30 2:00
|
||||
4:00 - MSK 2014 Oct 26 2:00s
|
||||
3:00 - MSK
|
||||
@ -3774,8 +3778,8 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
|
||||
# US colleague David Cochrane) are still trying to get more
|
||||
# information upon these local deviations from Kiev rules.
|
||||
#
|
||||
# From Paul Eggert (2022-02-08):
|
||||
# For now, assume that Ukraine's other three zones followed the same rules,
|
||||
# From Paul Eggert (2022-08-27):
|
||||
# For now, assume that Ukraine's zones all followed the same rules,
|
||||
# except that Crimea switched to Moscow time in 1994 as described elsewhere.
|
||||
|
||||
# From Igor Karpov, who works for the Ukrainian Ministry of Justice,
|
||||
@ -3845,21 +3849,7 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
|
||||
# * Ukrainian Government's Resolution of 20.03.1992, No. 139.
|
||||
# http://www.uazakon.com/documents/date_8u/pg_grcasa.htm
|
||||
|
||||
# From Paul Eggert (2022-04-12):
|
||||
# As is usual in tzdb, Ukrainian zones use the most common English spellings.
|
||||
# In particular, tzdb's name Europe/Kyiv uses the most common spelling in
|
||||
# English for Ukraine's capital. Although tzdb's former name was Europe/Kiev,
|
||||
# "Kyiv" is now more common due to widespread reporting of the current conflict.
|
||||
# Conversely, tzdb continues to use the names Europe/Uzhgorod and
|
||||
# Europe/Zaporozhye; this is similar to tzdb's use of Europe/Prague, which is
|
||||
# certainly wrong as a transliteration of the Czech "Praha".
|
||||
# English-language spelling of Ukrainian names is in flux, and
|
||||
# some day "Uzhhorod" or "Zaporizhzhia" may become substantially more
|
||||
# common in English; in the meantime, do not change these
|
||||
# English spellings as that means less disruption for our users.
|
||||
|
||||
# Zone NAME STDOFF RULES FORMAT [UNTIL]
|
||||
# This represents most of Ukraine. See above for the spelling of "Kyiv".
|
||||
Zone Europe/Kyiv 2:02:04 - LMT 1880
|
||||
2:02:04 - KMT 1924 May 2 # Kyiv Mean Time
|
||||
2:00 - EET 1930 Jun 21
|
||||
@ -3869,34 +3859,6 @@ Zone Europe/Kyiv 2:02:04 - LMT 1880
|
||||
2:00 1:00 EEST 1991 Sep 29 3:00
|
||||
2:00 C-Eur EE%sT 1996 May 13
|
||||
2:00 EU EE%sT
|
||||
# Transcarpathia used CET 1990/1991.
|
||||
# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
|
||||
# "Uzhgorod" is more common in English.
|
||||
Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct
|
||||
1:00 - CET 1940
|
||||
1:00 C-Eur CE%sT 1944 Oct
|
||||
1:00 1:00 CEST 1944 Oct 26
|
||||
1:00 - CET 1945 Jun 29
|
||||
3:00 Russia MSK/MSD 1990
|
||||
3:00 - MSK 1990 Jul 1 2:00
|
||||
1:00 - CET 1991 Mar 31 3:00
|
||||
2:00 - EET 1992 Mar 20
|
||||
2:00 C-Eur EE%sT 1996 May 13
|
||||
2:00 EU EE%sT
|
||||
# Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991.
|
||||
# "Zaporizhzhia" is the transliteration of the Ukrainian name, but
|
||||
# "Zaporozh'ye" is more common in English. Use the common English
|
||||
# spelling, except omit the apostrophe as it is not allowed in
|
||||
# portable Posix file names.
|
||||
Zone Europe/Zaporozhye 2:20:40 - LMT 1880
|
||||
2:20 - +0220 1924 May 2
|
||||
2:00 - EET 1930 Jun 21
|
||||
3:00 - MSK 1941 Aug 25
|
||||
1:00 C-Eur CE%sT 1943 Oct 25
|
||||
3:00 Russia MSK/MSD 1991 Mar 31 2:00
|
||||
2:00 E-Eur EE%sT 1992 Mar 20
|
||||
2:00 C-Eur EE%sT 1996 May 13
|
||||
2:00 EU EE%sT
|
||||
|
||||
# Vatican City
|
||||
# See Europe/Rome.
|
||||
|
||||
@ -1332,8 +1332,14 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
|
||||
# for America/Santiago will start on midnight of September 11th;
|
||||
# and will end on April 1st, 2023. Magallanes region (America/Punta_Arenas)
|
||||
# will keep UTC -3 "indefinitely"... This is because on September 4th
|
||||
# we will have a voting whether to approve a new Constitution....
|
||||
# https://www.interior.gob.cl/noticias/2022/08/09/comunicado-el-proximo-sabado-10-de-septiembre-los-relojes-se-deben-adelantar-una-hora/
|
||||
# we will have a voting whether to approve a new Constitution.
|
||||
#
|
||||
# From Eduardo Romero Urra (2022-08-17):
|
||||
# https://www.diariooficial.interior.gob.cl/publicaciones/2022/08/13/43327/01/2172567.pdf
|
||||
#
|
||||
# From Paul Eggert (2022-08-17):
|
||||
# Although the presidential decree stops at fall 2026, assume that
|
||||
# similar DST rules will continue thereafter.
|
||||
|
||||
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
|
||||
Rule Chile 1927 1931 - Sep 1 0:00 1:00 -
|
||||
|
||||
@ -424,8 +424,6 @@ TV -0831+17913 Pacific/Funafuti
|
||||
TW +2503+12130 Asia/Taipei
|
||||
TZ -0648+03917 Africa/Dar_es_Salaam
|
||||
UA +5026+03031 Europe/Kyiv Ukraine (most areas)
|
||||
UA +4837+02218 Europe/Uzhgorod Transcarpathia
|
||||
UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk
|
||||
UG +0019+03225 Africa/Kampala
|
||||
UM +2813-17722 Pacific/Midway Midway Islands
|
||||
UM +1917+16637 Pacific/Wake Wake Island
|
||||
|
||||
@ -555,58 +555,39 @@ findJavaTZ_md(const char *java_home_dir)
|
||||
/**
|
||||
* Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00")
|
||||
*/
|
||||
char *
|
||||
getGMTOffsetID()
|
||||
{
|
||||
char buf[32];
|
||||
char offset[6];
|
||||
struct tm localtm;
|
||||
time_t clock = time(NULL);
|
||||
if (localtime_r(&clock, &localtm) == NULL) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
|
||||
#if defined(MACOSX)
|
||||
|
||||
char *
|
||||
getGMTOffsetID()
|
||||
{
|
||||
time_t offset;
|
||||
char sign, buf[32];
|
||||
struct tm local_tm;
|
||||
time_t clock;
|
||||
|
||||
clock = time(NULL);
|
||||
if (localtime_r(&clock, &local_tm) == NULL) {
|
||||
time_t gmt_offset;
|
||||
gmt_offset = (time_t)localtm.tm_gmtoff;
|
||||
if (gmt_offset == 0) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
offset = (time_t)local_tm.tm_gmtoff;
|
||||
if (offset == 0) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
if (offset > 0) {
|
||||
sign = '+';
|
||||
} else {
|
||||
offset = -offset;
|
||||
sign = '-';
|
||||
}
|
||||
sprintf(buf, (const char *)"GMT%c%02d:%02d",
|
||||
sign, (int)(offset/3600), (int)((offset%3600)/60));
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char *
|
||||
getGMTOffsetID()
|
||||
{
|
||||
time_t offset;
|
||||
char sign, buf[32];
|
||||
offset = timezone;
|
||||
|
||||
if (offset == 0) {
|
||||
struct tm gmt;
|
||||
if (gmtime_r(&clock, &gmt) == NULL) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
|
||||
/* Note that the time offset direction is opposite. */
|
||||
if (offset > 0) {
|
||||
sign = '-';
|
||||
} else {
|
||||
offset = -offset;
|
||||
sign = '+';
|
||||
if(localtm.tm_hour == gmt.tm_hour && localtm.tm_min == gmt.tm_min) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
sprintf(buf, (const char *)"GMT%c%02d:%02d",
|
||||
sign, (int)(offset/3600), (int)((offset%3600)/60));
|
||||
#endif
|
||||
|
||||
if (strftime(offset, 6, "%z", &localtm) != 5) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
|
||||
sprintf(buf, (const char *)"GMT%c%c%c:%c%c", offset[0], offset[1], offset[2],
|
||||
offset[3], offset[4]);
|
||||
return strdup(buf);
|
||||
}
|
||||
#endif /* MACOSX */
|
||||
|
||||
@ -272,9 +272,9 @@ public abstract class Scope {
|
||||
}
|
||||
|
||||
private static class ScopeImpl extends WriteableScope {
|
||||
/** The number of scopes that share this scope's hash table.
|
||||
/** true if this scope's hash table is shared with a nested scope.
|
||||
*/
|
||||
private int shared;
|
||||
private boolean shared;
|
||||
|
||||
/** Next enclosing scope (with whom this scope may share a hashtable)
|
||||
*/
|
||||
@ -339,8 +339,10 @@ public abstract class Scope {
|
||||
* of fresh tables.
|
||||
*/
|
||||
public WriteableScope dup(Symbol newOwner) {
|
||||
Assert.check(!shared);
|
||||
|
||||
ScopeImpl result = new ScopeImpl(this, newOwner, this.table, this.nelems);
|
||||
shared++;
|
||||
shared = true;
|
||||
// System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
|
||||
// new Error().printStackTrace(System.out);
|
||||
return result;
|
||||
@ -351,7 +353,7 @@ public abstract class Scope {
|
||||
* the table of its outer scope.
|
||||
*/
|
||||
public WriteableScope dupUnshared(Symbol newOwner) {
|
||||
if (shared > 0) {
|
||||
if (shared) {
|
||||
//The nested Scopes might have already added something to the table, so all items
|
||||
//that don't originate in this Scope or any of its outer Scopes need to be cleared:
|
||||
Set<Scope> acceptScopes = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
@ -383,7 +385,7 @@ public abstract class Scope {
|
||||
* with next.
|
||||
*/
|
||||
public WriteableScope leave() {
|
||||
Assert.check(shared == 0);
|
||||
Assert.check(!shared);
|
||||
if (table != next.table) return next;
|
||||
while (elems != null) {
|
||||
int hash = getIndex(elems.sym.name);
|
||||
@ -392,8 +394,8 @@ public abstract class Scope {
|
||||
table[hash] = elems.shadowed;
|
||||
elems = elems.nextSibling;
|
||||
}
|
||||
Assert.check(next.shared > 0);
|
||||
next.shared--;
|
||||
Assert.check(next.shared);
|
||||
next.shared = false;
|
||||
next.nelems = nelems;
|
||||
// System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode());
|
||||
// new Error().printStackTrace(System.out);
|
||||
@ -403,12 +405,12 @@ public abstract class Scope {
|
||||
/** Double size of hash table.
|
||||
*/
|
||||
private void dble() {
|
||||
Assert.check(shared == 0);
|
||||
Assert.check(!shared);
|
||||
Entry[] oldtable = table;
|
||||
Entry[] newtable = new Entry[oldtable.length * 2];
|
||||
for (ScopeImpl s = this; s != null; s = s.next) {
|
||||
if (s.table == oldtable) {
|
||||
Assert.check(s == this || s.shared != 0);
|
||||
Assert.check(s == this || s.shared);
|
||||
s.table = newtable;
|
||||
s.hashMask = newtable.length - 1;
|
||||
}
|
||||
@ -429,7 +431,7 @@ public abstract class Scope {
|
||||
/** Enter symbol sym in this scope.
|
||||
*/
|
||||
public void enter(Symbol sym) {
|
||||
Assert.check(shared == 0);
|
||||
Assert.check(!shared);
|
||||
if (nelems * 3 >= hashMask * 2)
|
||||
dble();
|
||||
int hash = getIndex(sym.name);
|
||||
@ -449,7 +451,7 @@ public abstract class Scope {
|
||||
/** Remove symbol from this scope.
|
||||
*/
|
||||
public void remove(Symbol sym) {
|
||||
Assert.check(shared == 0);
|
||||
Assert.check(!shared);
|
||||
Entry e = lookup(sym.name, candidate -> candidate == sym);
|
||||
if (e.scope == null) return;
|
||||
|
||||
@ -487,7 +489,7 @@ public abstract class Scope {
|
||||
/** Enter symbol sym in this scope if not already there.
|
||||
*/
|
||||
public void enterIfAbsent(Symbol sym) {
|
||||
Assert.check(shared == 0);
|
||||
Assert.check(!shared);
|
||||
Entry e = lookup(sym.name);
|
||||
while (e.scope == this && e.sym.kind != sym.kind) e = e.next();
|
||||
if (e.scope != this) enter(sym);
|
||||
|
||||
@ -872,7 +872,7 @@ public class Attr extends JCTree.Visitor {
|
||||
Type itype = attribExpr(variable.init, env, type);
|
||||
if (variable.isImplicitlyTyped()) {
|
||||
//fixup local variable type
|
||||
type = variable.type = variable.sym.type = chk.checkLocalVarType(variable, itype.baseType(), variable.name);
|
||||
type = variable.type = variable.sym.type = chk.checkLocalVarType(variable, itype, variable.name);
|
||||
}
|
||||
if (itype.constValue() != null) {
|
||||
return coerce(itype, type).constValue();
|
||||
@ -1329,7 +1329,7 @@ public class Attr extends JCTree.Visitor {
|
||||
attribExpr(tree.init, initEnv, v.type);
|
||||
if (tree.isImplicitlyTyped()) {
|
||||
//fixup local variable type
|
||||
v.type = chk.checkLocalVarType(tree, tree.init.type.baseType(), tree.name);
|
||||
v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name);
|
||||
}
|
||||
}
|
||||
if (tree.isImplicitlyTyped()) {
|
||||
@ -1787,7 +1787,7 @@ public class Attr extends JCTree.Visitor {
|
||||
JCExpression guard = patternlabel.guard;
|
||||
if (guard != null) {
|
||||
MatchBindings afterPattern = matchBindings;
|
||||
Env<AttrContext> bodyEnv = bindingEnv(env, matchBindings.bindingsWhenTrue);
|
||||
Env<AttrContext> bodyEnv = bindingEnv(switchEnv, matchBindings.bindingsWhenTrue);
|
||||
try {
|
||||
attribExpr(guard, bodyEnv, syms.booleanType);
|
||||
} finally {
|
||||
@ -2620,7 +2620,7 @@ public class Attr extends JCTree.Visitor {
|
||||
argtypes.isEmpty()) {
|
||||
// as a special case, x.getClass() has type Class<? extends |X|>
|
||||
return new ClassType(restype.getEnclosingType(),
|
||||
List.of(new WildcardType(types.erasure(qualifierType),
|
||||
List.of(new WildcardType(types.erasure(qualifierType.baseType()),
|
||||
BoundKind.EXTENDS,
|
||||
syms.boundClass)),
|
||||
restype.tsym,
|
||||
|
||||
@ -993,7 +993,7 @@ public class Check {
|
||||
}
|
||||
|
||||
//upward project the initializer type
|
||||
return types.upward(t, types.captures(t));
|
||||
return types.upward(t, types.captures(t)).baseType();
|
||||
}
|
||||
|
||||
Type checkMethod(final Type mtype,
|
||||
|
||||
@ -497,6 +497,7 @@ public class Enter extends JCTree.Visitor {
|
||||
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
|
||||
c.classfile = c.sourcefile = env.toplevel.sourcefile;
|
||||
c.members_field = WriteableScope.create(c);
|
||||
c.isPermittedExplicit = tree.permitting.nonEmpty();
|
||||
c.clearAnnotationMetadata();
|
||||
|
||||
ClassType ct = (ClassType)c.type;
|
||||
|
||||
@ -733,14 +733,6 @@ public class TypeEnter implements Completer {
|
||||
}
|
||||
}
|
||||
|
||||
// Determine permits.
|
||||
ListBuffer<Symbol> permittedSubtypeSymbols = new ListBuffer<>();
|
||||
List<JCExpression> permittedTrees = tree.permitting;
|
||||
for (JCExpression permitted : permittedTrees) {
|
||||
Type pt = attr.attribBase(permitted, baseEnv, false, false, false);
|
||||
permittedSubtypeSymbols.append(pt.tsym);
|
||||
}
|
||||
|
||||
if ((sym.flags_field & ANNOTATION) != 0) {
|
||||
ct.interfaces_field = List.of(syms.annotationType);
|
||||
ct.all_interfaces_field = ct.interfaces_field;
|
||||
@ -749,15 +741,6 @@ public class TypeEnter implements Completer {
|
||||
ct.all_interfaces_field = (all_interfaces == null)
|
||||
? ct.interfaces_field : all_interfaces.toList();
|
||||
}
|
||||
|
||||
/* it could be that there are already some symbols in the permitted list, for the case
|
||||
* where there are subtypes in the same compilation unit but the permits list is empty
|
||||
* so don't overwrite the permitted list if it is not empty
|
||||
*/
|
||||
if (!permittedSubtypeSymbols.isEmpty()) {
|
||||
sym.permitted = permittedSubtypeSymbols.toList();
|
||||
}
|
||||
sym.isPermittedExplicit = !permittedSubtypeSymbols.isEmpty();
|
||||
}
|
||||
//where:
|
||||
protected JCExpression clearTypeParams(JCExpression superType) {
|
||||
@ -768,7 +751,7 @@ public class TypeEnter implements Completer {
|
||||
private final class HierarchyPhase extends AbstractHeaderPhase implements Completer {
|
||||
|
||||
public HierarchyPhase() {
|
||||
super(CompletionCause.HIERARCHY_PHASE, new PermitsPhase());
|
||||
super(CompletionCause.HIERARCHY_PHASE, new HeaderPhase());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -842,33 +825,6 @@ public class TypeEnter implements Completer {
|
||||
|
||||
}
|
||||
|
||||
private final class PermitsPhase extends AbstractHeaderPhase {
|
||||
|
||||
public PermitsPhase() {
|
||||
super(CompletionCause.HIERARCHY_PHASE, new HeaderPhase());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runPhase(Env<AttrContext> env) {
|
||||
JCClassDecl tree = env.enclClass;
|
||||
if (!tree.sym.isAnonymous() || tree.sym.isEnum()) {
|
||||
for (Type supertype : types.directSupertypes(tree.sym.type)) {
|
||||
if (supertype.tsym.kind == TYP) {
|
||||
ClassSymbol supClass = (ClassSymbol) supertype.tsym;
|
||||
Env<AttrContext> supClassEnv = enter.getEnv(supClass);
|
||||
if (supClass.isSealed() &&
|
||||
!supClass.isPermittedExplicit &&
|
||||
supClassEnv != null &&
|
||||
supClassEnv.toplevel == env.toplevel) {
|
||||
supClass.permitted = supClass.permitted.append(tree.sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class HeaderPhase extends AbstractHeaderPhase {
|
||||
|
||||
public HeaderPhase() {
|
||||
@ -892,6 +848,8 @@ public class TypeEnter implements Completer {
|
||||
|
||||
attribSuperTypes(env, baseEnv);
|
||||
|
||||
fillPermits(tree, baseEnv);
|
||||
|
||||
Set<Type> interfaceSet = new HashSet<>();
|
||||
|
||||
for (JCExpression iface : tree.implementing) {
|
||||
@ -920,6 +878,36 @@ public class TypeEnter implements Completer {
|
||||
sym.flags_field |= AUXILIARY;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillPermits(JCClassDecl tree, Env<AttrContext> baseEnv) {
|
||||
ClassSymbol sym = tree.sym;
|
||||
|
||||
//fill in implicit permits in supertypes:
|
||||
if (!sym.isAnonymous() || sym.isEnum()) {
|
||||
for (Type supertype : types.directSupertypes(sym.type)) {
|
||||
if (supertype.tsym.kind == TYP) {
|
||||
ClassSymbol supClass = (ClassSymbol) supertype.tsym;
|
||||
Env<AttrContext> supClassEnv = enter.getEnv(supClass);
|
||||
if (supClass.isSealed() &&
|
||||
!supClass.isPermittedExplicit &&
|
||||
supClassEnv != null &&
|
||||
supClassEnv.toplevel == baseEnv.toplevel) {
|
||||
supClass.permitted = supClass.permitted.append(sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// attribute (explicit) permits of the current class:
|
||||
if (sym.isPermittedExplicit) {
|
||||
ListBuffer<Symbol> permittedSubtypeSymbols = new ListBuffer<>();
|
||||
List<JCExpression> permittedTrees = tree.permitting;
|
||||
for (JCExpression permitted : permittedTrees) {
|
||||
Type pt = attr.attribBase(permitted, baseEnv, false, false, false);
|
||||
permittedSubtypeSymbols.append(pt.tsym);
|
||||
}
|
||||
sym.permitted = permittedSubtypeSymbols.toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class AbstractMembersPhase extends Phase {
|
||||
|
||||
69
test/hotspot/jtreg/compiler/c1/BadStateAtLongCmp.jasm
Normal file
69
test/hotspot/jtreg/compiler/c1/BadStateAtLongCmp.jasm
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
super public class BadStateAtLongCmp
|
||||
version 52:0
|
||||
{
|
||||
public static Field field:I;
|
||||
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Same as:
|
||||
public static void test() {
|
||||
long l = 0;
|
||||
do {
|
||||
l++;
|
||||
field++;
|
||||
} while (l < 1000);
|
||||
}
|
||||
but with field++ between the lcmp and iflt bytecodes.
|
||||
*/
|
||||
public static Method test:"()V"
|
||||
stack 4 locals 2
|
||||
{
|
||||
lconst_0;
|
||||
lstore_0;
|
||||
L2: stack_frame_type append;
|
||||
locals_map long;
|
||||
lload_0;
|
||||
lconst_1;
|
||||
ladd;
|
||||
lstore_0;
|
||||
lload_0;
|
||||
ldc2_w long 1000l;
|
||||
lcmp;
|
||||
getstatic Field field:"I";
|
||||
iconst_1;
|
||||
iadd;
|
||||
putstatic Field field:"I";
|
||||
iflt L2;
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class BadStateAtLongCmp
|
||||
86
test/hotspot/jtreg/compiler/c1/KlassAccessCheck.jasm
Normal file
86
test/hotspot/jtreg/compiler/c1/KlassAccessCheck.jasm
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package compiler/c1;
|
||||
|
||||
super public class KlassAccessCheck
|
||||
version 51:0
|
||||
{
|
||||
|
||||
public static Method testNewInstance:"()V"
|
||||
stack 2 locals 0
|
||||
{
|
||||
new class compiler/c1/types/PackagePrivateClass;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public static Method testNewArray:"()[Ljava/lang/Object;"
|
||||
stack 1 locals 0
|
||||
{
|
||||
iconst_1;
|
||||
anewarray class compiler/c1/types/PackagePrivateClass;
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method testMultiNewArray:"()[[Ljava/lang/Object;"
|
||||
stack 2 locals 1
|
||||
{
|
||||
iconst_1;
|
||||
iconst_1;
|
||||
multianewarray class "[[Lcompiler/c1/types/PackagePrivateClass;", 2;
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method testCheckCast:"(Ljava/lang/Object;)Ljava/lang/Object;"
|
||||
stack 1 locals 2
|
||||
{
|
||||
aload_0;
|
||||
checkcast class compiler/c1/types/PackagePrivateClass;
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method testCheckCastArr:"(Ljava/lang/Object;)Ljava/lang/Object;"
|
||||
stack 1 locals 2
|
||||
{
|
||||
aload_0;
|
||||
checkcast class "[Lcompiler/c1/types/PackagePrivateClass;";
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method testInstanceOf:"(Ljava/lang/Object;)Z"
|
||||
stack 1 locals 2
|
||||
{
|
||||
aload_0;
|
||||
instanceof class compiler/c1/types/PackagePrivateClass;
|
||||
ireturn;
|
||||
}
|
||||
|
||||
public static Method testInstanceOfArr:"(Ljava/lang/Object;)Z"
|
||||
stack 1 locals 2
|
||||
{
|
||||
aload_0;
|
||||
instanceof class "[Lcompiler/c1/types/PackagePrivateClass;";
|
||||
ireturn;
|
||||
}
|
||||
} // end Class KlassAccessCheck
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package compiler/c1/types;
|
||||
|
||||
super class PackagePrivateClass
|
||||
version 51:0
|
||||
{}
|
||||
|
||||
61
test/hotspot/jtreg/compiler/c1/KlassAccessCheckTest.java
Normal file
61
test/hotspot/jtreg/compiler/c1/KlassAccessCheckTest.java
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8293044
|
||||
* @requires vm.compiler1.enabled
|
||||
* @compile KlassAccessCheckPackagePrivate.jasm
|
||||
* @compile KlassAccessCheck.jasm
|
||||
* @run main/othervm -Xbatch -XX:TieredStopAtLevel=1 compiler.c1.KlassAccessCheckTest
|
||||
*/
|
||||
|
||||
package compiler.c1;
|
||||
|
||||
public class KlassAccessCheckTest {
|
||||
static void test(Runnable r) {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
try {
|
||||
r.run();
|
||||
throw new AssertionError("No IllegalAccessError thrown");
|
||||
} catch (IllegalAccessError e) {
|
||||
// Expected
|
||||
} catch (AssertionError e) {
|
||||
throw e; // rethrow
|
||||
} catch (Throwable e) {
|
||||
throw new AssertionError("Wrong exception thrown", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(() -> KlassAccessCheck.testNewInstance());
|
||||
test(() -> KlassAccessCheck.testNewArray());
|
||||
test(() -> KlassAccessCheck.testMultiNewArray());
|
||||
test(() -> KlassAccessCheck.testCheckCast(42));
|
||||
test(() -> KlassAccessCheck.testCheckCastArr(new Integer[0]));
|
||||
test(() -> KlassAccessCheck.testInstanceOf(42));
|
||||
test(() -> KlassAccessCheck.testInstanceOfArr(new Integer[0]));
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
43
test/hotspot/jtreg/compiler/c1/TestBadStateAtLongCmp.java
Normal file
43
test/hotspot/jtreg/compiler/c1/TestBadStateAtLongCmp.java
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290451
|
||||
* @summary Incorrect result when switching to C2 OSR compilation from C1
|
||||
* @compile BadStateAtLongCmp.jasm
|
||||
* @run main/othervm -Xbatch TestBadStateAtLongCmp
|
||||
*/
|
||||
|
||||
public class TestBadStateAtLongCmp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
BadStateAtLongCmp.test();
|
||||
}
|
||||
int expected = 20_000 * 1000;
|
||||
if (BadStateAtLongCmp.field != expected) {
|
||||
throw new RuntimeException("test failed: " + BadStateAtLongCmp.field + " != " + expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,9 @@
|
||||
* compiler.c2.Test7179138_1
|
||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN compiler.c2.Test7179138_1
|
||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+AlwaysIncrementalInline
|
||||
* compiler.c2.Test7179138_1
|
||||
*
|
||||
* @author Skip Balk
|
||||
*/
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290529
|
||||
* @summary C2: assert(BoolTest(btest).is_canonical()) failure
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:-TieredCompilation TestUnsignedCompareIntoEqualityNotCanonical
|
||||
*/
|
||||
|
||||
|
||||
public class TestUnsignedCompareIntoEqualityNotCanonical {
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test(0);
|
||||
test(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static int test(int x) {
|
||||
if (Integer.compareUnsigned(0, x) >= 0) {
|
||||
return 42;
|
||||
}
|
||||
return -42;
|
||||
}
|
||||
}
|
||||
60
test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java
Normal file
60
test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package compiler.c2.irTests;
|
||||
|
||||
import compiler.lib.ir_framework.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* bug 8290529
|
||||
* @summary verify that x <u 1 is transformed to x == 0
|
||||
* @requires os.arch=="amd64" | os.arch=="x86_64"
|
||||
* @library /test/lib /
|
||||
* @requires vm.compiler2.enabled
|
||||
* @run driver compiler.c2.irTests.CmpUWithZero
|
||||
*/
|
||||
|
||||
public class CmpUWithZero {
|
||||
static volatile boolean field;
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void test(int x) {
|
||||
if (Integer.compareUnsigned(x, 1) < 0) {
|
||||
field = true;
|
||||
} else {
|
||||
field = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Run(test = "test")
|
||||
private void testRunner() {
|
||||
test(0);
|
||||
test(42);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290711
|
||||
* @summary assert(false) failed: infinite loop in PhaseIterGVN::optimize
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:-TieredCompilation TestInfiniteIGVNAfterCCP
|
||||
*/
|
||||
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
public class TestInfiniteIGVNAfterCCP {
|
||||
private static int inc;
|
||||
private static volatile boolean barrier;
|
||||
|
||||
static class A {
|
||||
int field1;
|
||||
int field2;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
A a = new A();
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test(false, a, false);
|
||||
inc = 0;
|
||||
testHelper(true, () -> inc < 10, a, 4, true);
|
||||
inc = 0;
|
||||
testHelper(true, () -> inc < 10, a, 4, false);
|
||||
testHelper(false, () -> inc < 10, a, 42, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void test(boolean flag2, A a, boolean flag1) {
|
||||
int i = 2;
|
||||
for (; i < 4; i *= 2);
|
||||
testHelper(flag2, () -> true, a, i, flag1);
|
||||
}
|
||||
|
||||
private static void testHelper(boolean flag2, BooleanSupplier f, A a, int i, boolean flag1) {
|
||||
if (i == 4) {
|
||||
if (a == null) {
|
||||
|
||||
}
|
||||
} else {
|
||||
a = null;
|
||||
}
|
||||
if (flag2) {
|
||||
while (true) {
|
||||
synchronized (new Object()) {
|
||||
|
||||
}
|
||||
if (!f.getAsBoolean()) {
|
||||
break;
|
||||
}
|
||||
if (flag1) {
|
||||
if (a == null) {
|
||||
|
||||
}
|
||||
}
|
||||
barrier = true;
|
||||
inc++;
|
||||
if (inc % 2 == 0) {
|
||||
a.field1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8291599
|
||||
* @summary Assertion in PhaseIdealLoop::skeleton_predicate_has_opaque after JDK-8289127
|
||||
* @requires vm.compiler2.enabled
|
||||
*
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:LoopMaxUnroll=0 TestPhiInSkeletonPredicateExpression
|
||||
*/
|
||||
|
||||
public class TestPhiInSkeletonPredicateExpression {
|
||||
private static int[] array1;
|
||||
private static int[] array2;
|
||||
private static int off;
|
||||
private static volatile int barrier;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] array = new int[2000];
|
||||
array1 = array;
|
||||
array2 = array;
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test1(1000, false);
|
||||
test1(1000, true);
|
||||
test2(1000, false);
|
||||
test2(1000, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static int test1(int stop, boolean flag) {
|
||||
int v = 0;
|
||||
|
||||
for (int j = 1; j < 10; j *= 2) {
|
||||
int[] array;
|
||||
if (flag) {
|
||||
if (array1 == null) {
|
||||
|
||||
}
|
||||
array = array1;
|
||||
barrier = 0x42;
|
||||
} else {
|
||||
if (array2 == null) {
|
||||
|
||||
}
|
||||
array = array2;
|
||||
barrier = 0x42;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
synchronized (new Object()) {
|
||||
}
|
||||
v += array[i + off];
|
||||
i++;
|
||||
} while (i < stop);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static int test2(int stop, boolean flag) {
|
||||
int v = 0;
|
||||
|
||||
int[] array;
|
||||
if (flag) {
|
||||
if (array1 == null) {
|
||||
|
||||
}
|
||||
array = array1;
|
||||
barrier = 0x42;
|
||||
} else {
|
||||
if (array2 == null) {
|
||||
|
||||
}
|
||||
array = array2;
|
||||
barrier = 0x42;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
synchronized (new Object()) {
|
||||
}
|
||||
v += array[i + off];
|
||||
i++;
|
||||
} while (i < stop);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290781
|
||||
* @summary Segfault at PhaseIdealLoop::clone_loop_handle_data_uses
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:-TieredCompilation TestLSMBadControlOverride
|
||||
*/
|
||||
|
||||
public class TestLSMBadControlOverride {
|
||||
private static volatile int barrier;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] array = new int[100];
|
||||
int[] small = new int[10];
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test(array, array, true, true);
|
||||
test(array, array, true, false);
|
||||
test(array, array, false, false);
|
||||
try {
|
||||
test(small, array,true, true);
|
||||
} catch (ArrayIndexOutOfBoundsException aieoobe) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int test(int[] array, int[] array2, boolean flag1, boolean flag2) {
|
||||
int i;
|
||||
int v = 0;
|
||||
int v1 = 0;
|
||||
for (i = 0; i < 100; i++) {
|
||||
v1 = array[i];
|
||||
}
|
||||
v += v1;
|
||||
if (flag1) {
|
||||
if (flag2) {
|
||||
barrier = 42;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 100; j++) {
|
||||
array[j] = j;
|
||||
v += array[i-1];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
super public class compiler/stringopts/SideEffectBeforeConstructor
|
||||
version 51:0
|
||||
{
|
||||
public static Field result:I;
|
||||
|
||||
static Method "<clinit>":"()V"
|
||||
stack 2 locals 0
|
||||
{
|
||||
iconst_0;
|
||||
putstatic Field result:"I";
|
||||
return;
|
||||
}
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
public static Method test:"(Ljava/lang/String;)V"
|
||||
stack 4 locals 1
|
||||
{
|
||||
new class java/lang/StringBuffer;
|
||||
dup;
|
||||
getstatic Field result:"I";
|
||||
iconst_1;
|
||||
iadd;
|
||||
putstatic Field result:"I";
|
||||
aload_0;
|
||||
invokespecial Method java/lang/StringBuffer."<init>":"(Ljava/lang/String;)V";
|
||||
invokevirtual Method java/lang/StringBuffer.toString:"()Ljava/lang/String;";
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290705
|
||||
* @summary Test correctness of the string concatenation optimization with
|
||||
* a store between StringBuffer allocation and constructor invocation.
|
||||
* @compile SideEffectBeforeConstructor.jasm
|
||||
* @run main/othervm -Xbatch compiler.stringopts.TestSideEffectBeforeConstructor
|
||||
*/
|
||||
|
||||
package compiler.stringopts;
|
||||
|
||||
public class TestSideEffectBeforeConstructor {
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 100_000; ++i) {
|
||||
try {
|
||||
SideEffectBeforeConstructor.test(null);
|
||||
} catch (NullPointerException npe) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
if (SideEffectBeforeConstructor.result != 100_000) {
|
||||
throw new RuntimeException("Unexpected result: " + SideEffectBeforeConstructor.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,6 +41,7 @@
|
||||
* Fixed according to the 4480280 bug.
|
||||
* Ported from JVMDI.
|
||||
*
|
||||
* @requires vm.jvmti & vm.continuations
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @build nsk.jvmti.GetThreadInfo.thrinfo001
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
*
|
||||
* @key randomness
|
||||
*
|
||||
* @requires vm.jvmti & vm.continuations
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @build nsk.jvmti.RedefineClasses.StressRedefine
|
||||
|
||||
77
test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java
Normal file
77
test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8285838
|
||||
* @library /test/lib
|
||||
* @summary This test will ensure that daylight savings rules are followed
|
||||
* appropriately when setting a custom timezone ID via the TZ env variable.
|
||||
* @requires os.family != "windows"
|
||||
* @run main/othervm CustomTzIDCheckDST
|
||||
*/
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
public class CustomTzIDCheckDST {
|
||||
private static String CUSTOM_TZ = "MEZ-1MESZ,M3.5.0,M10.5.0";
|
||||
public static void main(String args[]) throws Throwable {
|
||||
if (args.length == 0) {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(List.of("CustomTzIDCheckDST", "runTZTest"));
|
||||
pb.environment().put("TZ", CUSTOM_TZ);
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(pb);
|
||||
output.shouldHaveExitValue(0);
|
||||
} else {
|
||||
runTZTest();
|
||||
}
|
||||
}
|
||||
|
||||
/* TZ code will always be set to "MEZ-1MESZ,M3.5.0,M10.5.0".
|
||||
* This ensures the transition periods for Daylights Savings should be at March's last
|
||||
* Sunday and October's last Sunday.
|
||||
*/
|
||||
private static void runTZTest() {
|
||||
Date time = new Date();
|
||||
if (new SimpleTimeZone(3600000, "MEZ-1MESZ", Calendar.MARCH, -1, Calendar.SUNDAY, 0,
|
||||
Calendar.OCTOBER, -1, Calendar.SUNDAY, 0).inDaylightTime(time)) {
|
||||
// We are in Daylight savings period.
|
||||
if (time.toString().endsWith("GMT+02:00 " + Integer.toString(time.getYear() + 1900)))
|
||||
return;
|
||||
} else {
|
||||
if (time.toString().endsWith("GMT+01:00 " + Integer.toString(time.getYear() + 1900)))
|
||||
return;
|
||||
}
|
||||
|
||||
// Reaching here means time zone did not match up as expected.
|
||||
throw new RuntimeException("Got unexpected timezone information: " + time);
|
||||
}
|
||||
|
||||
private static ZonedDateTime getLastSundayOfMonth(ZonedDateTime date) {
|
||||
return date.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
|
||||
}
|
||||
}
|
||||
@ -1 +1 @@
|
||||
tzdata2022c
|
||||
tzdata2022d
|
||||
|
||||
@ -183,6 +183,8 @@ Link Etc/UTC Etc/UCT
|
||||
Link Europe/London Europe/Belfast
|
||||
Link Europe/Kyiv Europe/Kiev
|
||||
Link Europe/Chisinau Europe/Tiraspol
|
||||
Link Europe/Kyiv Europe/Uzhgorod
|
||||
Link Europe/Kyiv Europe/Zaporozhye
|
||||
Link Europe/London GB
|
||||
Link Europe/London GB-Eire
|
||||
Link Etc/GMT GMT+0
|
||||
|
||||
@ -163,11 +163,9 @@ Europe/Simferopol MSK
|
||||
Europe/Sofia EET EEST
|
||||
Europe/Tallinn EET EEST
|
||||
Europe/Tirane CET CEST
|
||||
Europe/Uzhgorod EET EEST
|
||||
Europe/Vienna CET CEST
|
||||
Europe/Vilnius EET EEST
|
||||
Europe/Warsaw CET CEST
|
||||
Europe/Zaporozhye EET EEST
|
||||
Europe/Zurich CET CEST
|
||||
HST HST
|
||||
MET MET MEST
|
||||
|
||||
@ -176,11 +176,12 @@ public class TestZoneInfo310 {
|
||||
* save time in IANA tzdata. This bug is tracked via JDK-8223388.
|
||||
*
|
||||
* These are the zones/rules that employ negative DST in vanguard
|
||||
* format (as of 2019a):
|
||||
* format (as of 2019a), Palestine added in 2022d:
|
||||
*
|
||||
* - Rule "Eire"
|
||||
* - Rule "Morocco"
|
||||
* - Rule "Namibia"
|
||||
* - Rule "Palestine"
|
||||
* - Zone "Europe/Prague"
|
||||
*
|
||||
* Tehran/Iran rule has rules beyond 2037, in which javazic assumes
|
||||
@ -196,6 +197,8 @@ public class TestZoneInfo310 {
|
||||
zid.equals("Europe/Dublin") || // uses "Eire" rule
|
||||
zid.equals("Europe/Prague") ||
|
||||
zid.equals("Asia/Tehran") || // last rule mismatch
|
||||
zid.equals("Asia/Gaza") || // uses "Palestine" rule
|
||||
zid.equals("Asia/Hebron") || // uses "Palestine" rule
|
||||
zid.equals("Iran")) { // last rule mismatch
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8181157 8202537 8234347 8236548 8261279
|
||||
* @bug 8181157 8202537 8234347 8236548 8261279 8293834
|
||||
* @modules jdk.localedata
|
||||
* @summary Checks CLDR time zone names are generated correctly at runtime
|
||||
* @run testng/othervm -Djava.locale.providers=CLDR TimeZoneNamesTest
|
||||
@ -102,6 +102,24 @@ public class TimeZoneNamesTest {
|
||||
"UTC+04:00",
|
||||
"heure : Astrakhan",
|
||||
"UTC+04:00"},
|
||||
{"Europe/Kyiv", Locale.US, "Eastern European Standard Time",
|
||||
"GMT+02:00",
|
||||
"Eastern European Summer Time",
|
||||
"GMT+03:00",
|
||||
"Eastern European Time",
|
||||
"GMT+02:00"},
|
||||
{"Europe/Kyiv", Locale.FRANCE, "heure normale d\u2019Europe de l\u2019Est",
|
||||
"UTC+02:00",
|
||||
"heure d\u2019\u00e9t\u00e9 d\u2019Europe de l\u2019Est",
|
||||
"UTC+03:00",
|
||||
"heure d\u2019Europe de l\u2019Est",
|
||||
"UTC+02:00"},
|
||||
{"Europe/Kyiv", Locale.GERMANY, "Osteurop\u00e4ische Normalzeit",
|
||||
"OEZ",
|
||||
"Osteurop\u00e4ische Sommerzeit",
|
||||
"OESZ",
|
||||
"Osteurop\u00e4ische Zeit",
|
||||
"OEZ"},
|
||||
{"Europe/Saratov", Locale.US, "Saratov Standard Time",
|
||||
"GMT+04:00",
|
||||
"Saratov Daylight Time",
|
||||
|
||||
99
test/langtools/tools/javac/lvti/ConstantTypes.java
Normal file
99
test/langtools/tools/javac/lvti/ConstantTypes.java
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8293578
|
||||
* @summary Ensure constant types are removed correctly for <string>.getClass().
|
||||
* @compile ConstantTypes.java
|
||||
* @run main ConstantTypes
|
||||
*/
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ConstantTypes {
|
||||
public static void main(String... args) throws Throwable {
|
||||
new ConstantTypes().testStringCreation1();
|
||||
new ConstantTypes().testStringCreation2();
|
||||
new ConstantTypes().testStringCreation3();
|
||||
new ConstantTypes().testStringCreation4();
|
||||
new ConstantTypes().testStringFolding();
|
||||
}
|
||||
|
||||
private void testStringCreation1() throws Throwable {
|
||||
var testC = "incorrect".getClass();
|
||||
var testV = testC.getConstructor(String.class)
|
||||
.newInstance("correct");
|
||||
String actual = testV;
|
||||
String expected = "correct";
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError("Unexpected result: " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
private void testStringCreation2() throws Throwable {
|
||||
var test = "incorrect".getClass()
|
||||
.getConstructor(String.class)
|
||||
.newInstance("correct");
|
||||
String actual = test;
|
||||
String expected = "correct";
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError("Unexpected result: " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
private void testStringCreation3() throws Throwable {
|
||||
final var testC = "incorrect";
|
||||
var testV = testC.getClass()
|
||||
.getConstructor(String.class)
|
||||
.newInstance("correct");
|
||||
String actual = testV;
|
||||
String expected = "correct";
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError("Unexpected result: " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
private void testStringCreation4() throws Throwable {
|
||||
var testC = "incorrect";
|
||||
var testV = testC.getClass()
|
||||
.getConstructor(String.class)
|
||||
.newInstance("correct");
|
||||
String actual = testV;
|
||||
String expected = "correct";
|
||||
if (!Objects.equals(actual, expected)) {
|
||||
throw new AssertionError("Unexpected result: " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
private void testStringFolding() {
|
||||
final var v1 = "1";
|
||||
final var v2 = "2";
|
||||
String actual = v1 + v2;
|
||||
String expected = "12";
|
||||
if (actual != expected) { //intentional reference comparison
|
||||
throw new AssertionError("Value not interned!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
104
test/langtools/tools/javac/patterns/ScopeResizeTest.java
Normal file
104
test/langtools/tools/javac/patterns/ScopeResizeTest.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8292756
|
||||
* @summary Verify the Scope can be safely and correctly resized to accommodate pattern binding variables
|
||||
* when the Scope for a guard is constructed.
|
||||
* @library /tools/lib /tools/javac/lib
|
||||
* @modules
|
||||
* jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.file
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* jdk.compiler/com.sun.tools.javac.util
|
||||
* @build toolbox.ToolBox toolbox.JavacTask
|
||||
* @build combo.ComboTestHelper
|
||||
* @compile ScopeResizeTest.java
|
||||
* @run main ScopeResizeTest
|
||||
*/
|
||||
|
||||
import combo.ComboInstance;
|
||||
import combo.ComboParameter;
|
||||
import combo.ComboTask;
|
||||
import combo.ComboTestHelper;
|
||||
import java.util.stream.Stream;
|
||||
import toolbox.ToolBox;
|
||||
|
||||
public class ScopeResizeTest extends ComboInstance<ScopeResizeTest> {
|
||||
protected ToolBox tb;
|
||||
|
||||
ScopeResizeTest() {
|
||||
super();
|
||||
tb = new ToolBox();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
int variantsSize = 17;
|
||||
PredefinedVariables[] variants = Stream.iterate(0, i -> i + 1)
|
||||
.limit(variantsSize)
|
||||
.map(s -> new PredefinedVariables(s))
|
||||
.toArray(s -> new PredefinedVariables[s]);
|
||||
new ComboTestHelper<ScopeResizeTest>()
|
||||
.withDimension("PREDEFINED_VARIABLES", (x, predefinedVariables) -> x.predefinedVariables = predefinedVariables, variants)
|
||||
.run(ScopeResizeTest::new);
|
||||
}
|
||||
|
||||
private PredefinedVariables predefinedVariables;
|
||||
|
||||
private static final String MAIN_TEMPLATE =
|
||||
"""
|
||||
public class Test {
|
||||
public static void test(Object o) {
|
||||
#{PREDEFINED_VARIABLES}
|
||||
switch (o) {
|
||||
case String s when s.isEmpty() -> {}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
@Override
|
||||
protected void doWork() throws Throwable {
|
||||
ComboTask task = newCompilationTask()
|
||||
.withSourceFromTemplate(MAIN_TEMPLATE, pname -> switch (pname) {
|
||||
case "PREDEFINED_VARIABLES" -> predefinedVariables;
|
||||
default -> throw new UnsupportedOperationException(pname);
|
||||
});
|
||||
|
||||
task.analyze(result -> {});
|
||||
}
|
||||
|
||||
public record PredefinedVariables(int size) implements ComboParameter {
|
||||
@Override
|
||||
public String expand(String optParameter) {
|
||||
StringBuilder variables = new StringBuilder();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
variables.append("int i" + i + ";\n");
|
||||
}
|
||||
return variables.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test 8247352
|
||||
* @test 8247352 8293348
|
||||
* @summary test different configurations of sealed classes, same compilation unit, diff pkg or mdl, etc
|
||||
* @library /tools/lib
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
@ -662,4 +662,35 @@ public class SealedDiffConfigurationsTest extends TestRunner {
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
}
|
||||
|
||||
@Test //JDK-8293348
|
||||
public void testSupertypePermitsLoop(Path base) throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
|
||||
tb.writeJavaFiles(src,
|
||||
"class Main implements T2 {}",
|
||||
"non-sealed interface T2 extends T {}",
|
||||
"sealed interface T permits T2 {}");
|
||||
|
||||
Path out = base.resolve("out");
|
||||
|
||||
Files.createDirectories(out);
|
||||
|
||||
new JavacTask(tb)
|
||||
.outdir(out)
|
||||
.files(findJavaFiles(src))
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
Files.delete(out.resolve("Main.class"));
|
||||
Files.delete(out.resolve("T.class"));
|
||||
|
||||
new JavacTask(tb)
|
||||
.outdir(out)
|
||||
.options("-cp", out.toString(),
|
||||
"-sourcepath", src.toString())
|
||||
.files(src.resolve("Main.java"))
|
||||
.run()
|
||||
.writeAll();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user