This commit is contained in:
Jesper Wilhelmsson 2020-01-13 15:40:09 +01:00
commit 913b8702d1
59 changed files with 834 additions and 306 deletions

View file

@ -294,7 +294,7 @@ void PatchingStub::align_patch_site(MacroAssembler* masm) {
void PatchingStub::emit_code(LIR_Assembler* ce) { void PatchingStub::emit_code(LIR_Assembler* ce) {
// Copy original code here. // Copy original code here.
assert(NativeGeneralJump::instruction_size <= _bytes_to_copy && _bytes_to_copy <= 0xFF, assert(NativeGeneralJump::instruction_size <= _bytes_to_copy && _bytes_to_copy <= 0xFF,
"not enough room for call"); "not enough room for call, need %d", _bytes_to_copy);
NearLabel call_patch; NearLabel call_patch;
@ -331,7 +331,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
} }
#endif #endif
} else { } else {
// Make a copy the code which is going to be patched. // Make a copy of the code which is going to be patched.
for (int i = 0; i < _bytes_to_copy; i++) { for (int i = 0; i < _bytes_to_copy; i++) {
address ptr = (address)(_pc_start + i); address ptr = (address)(_pc_start + i);
int a_byte = (*ptr) & 0xFF; int a_byte = (*ptr) & 0xFF;

View file

@ -897,7 +897,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, LIR_P
bool needs_patching = (patch_code != lir_patch_none); bool needs_patching = (patch_code != lir_patch_none);
if (addr->base()->type() == T_OBJECT) { if (addr->base()->type() == T_OBJECT) {
__ verify_oop(src); __ verify_oop(src, FILE_AND_LINE);
} }
PatchingStub* patch = NULL; PatchingStub* patch = NULL;
@ -972,7 +972,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, LIR_P
} else { } else {
__ z_lg(dest->as_register(), disp_value, disp_reg, src); __ z_lg(dest->as_register(), disp_value, disp_reg, src);
} }
__ verify_oop(dest->as_register()); __ verify_oop(dest->as_register(), FILE_AND_LINE);
break; break;
} }
case T_FLOAT: case T_FLOAT:
@ -1006,7 +1006,7 @@ void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) {
if (dest->is_single_cpu()) { if (dest->is_single_cpu()) {
if (is_reference_type(type)) { if (is_reference_type(type)) {
__ mem2reg_opt(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()), true); __ mem2reg_opt(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()), true);
__ verify_oop(dest->as_register()); __ verify_oop(dest->as_register(), FILE_AND_LINE);
} else if (type == T_METADATA || type == T_ADDRESS) { } else if (type == T_METADATA || type == T_ADDRESS) {
__ mem2reg_opt(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()), true); __ mem2reg_opt(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()), true);
} else { } else {
@ -1033,7 +1033,7 @@ void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool po
if (src->is_single_cpu()) { if (src->is_single_cpu()) {
const Address dst = frame_map()->address_for_slot(dest->single_stack_ix()); const Address dst = frame_map()->address_for_slot(dest->single_stack_ix());
if (is_reference_type(type)) { if (is_reference_type(type)) {
__ verify_oop(src->as_register()); __ verify_oop(src->as_register(), FILE_AND_LINE);
__ reg2mem_opt(src->as_register(), dst, true); __ reg2mem_opt(src->as_register(), dst, true);
} else if (type == T_METADATA || type == T_ADDRESS) { } else if (type == T_METADATA || type == T_ADDRESS) {
__ reg2mem_opt(src->as_register(), dst, true); __ reg2mem_opt(src->as_register(), dst, true);
@ -1079,7 +1079,7 @@ void LIR_Assembler::reg2reg(LIR_Opr from_reg, LIR_Opr to_reg) {
ShouldNotReachHere(); ShouldNotReachHere();
} }
if (is_reference_type(to_reg->type())) { if (is_reference_type(to_reg->type())) {
__ verify_oop(to_reg->as_register()); __ verify_oop(to_reg->as_register(), FILE_AND_LINE);
} }
} }
@ -1095,7 +1095,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from, LIR_Opr dest_opr, BasicType type,
bool needs_patching = (patch_code != lir_patch_none); bool needs_patching = (patch_code != lir_patch_none);
if (addr->base()->is_oop_register()) { if (addr->base()->is_oop_register()) {
__ verify_oop(dest); __ verify_oop(dest, FILE_AND_LINE);
} }
PatchingStub* patch = NULL; PatchingStub* patch = NULL;
@ -1130,7 +1130,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from, LIR_Opr dest_opr, BasicType type,
assert(disp_reg != Z_R0 || Immediate::is_simm20(disp_value), "should have set this up"); assert(disp_reg != Z_R0 || Immediate::is_simm20(disp_value), "should have set this up");
if (is_reference_type(type)) { if (is_reference_type(type)) {
__ verify_oop(from->as_register()); __ verify_oop(from->as_register(), FILE_AND_LINE);
} }
bool short_disp = Immediate::is_uimm12(disp_value); bool short_disp = Immediate::is_uimm12(disp_value);
@ -2412,7 +2412,7 @@ void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) {
op->klass()->as_register(), op->klass()->as_register(),
*op->stub()->entry()); *op->stub()->entry());
__ bind(*op->stub()->continuation()); __ bind(*op->stub()->continuation());
__ verify_oop(op->obj()->as_register()); __ verify_oop(op->obj()->as_register(), FILE_AND_LINE);
} }
void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
@ -2548,7 +2548,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
} }
assert(obj != k_RInfo, "must be different"); assert(obj != k_RInfo, "must be different");
__ verify_oop(obj); __ verify_oop(obj, FILE_AND_LINE);
// Get object class. // Get object class.
// Not a safepoint as obj null check happens earlier. // Not a safepoint as obj null check happens earlier.
@ -3009,7 +3009,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
assert(do_null || do_update, "why are we here?"); assert(do_null || do_update, "why are we here?");
assert(!TypeEntries::was_null_seen(current_klass) || do_update, "why are we here?"); assert(!TypeEntries::was_null_seen(current_klass) || do_update, "why are we here?");
__ verify_oop(obj); __ verify_oop(obj, FILE_AND_LINE);
if (do_null || tmp1 != obj DEBUG_ONLY(|| true)) { if (do_null || tmp1 != obj DEBUG_ONLY(|| true)) {
__ z_ltgr(tmp1, obj); __ z_ltgr(tmp1, obj);

View file

@ -40,7 +40,7 @@
void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
Label ic_miss, ic_hit; Label ic_miss, ic_hit;
verify_oop(receiver); verify_oop(receiver, FILE_AND_LINE);
int klass_offset = oopDesc::klass_offset_in_bytes(); int klass_offset = oopDesc::klass_offset_in_bytes();
if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) { if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) {
@ -83,7 +83,7 @@ void C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hd
assert_different_registers(hdr, obj, disp_hdr); assert_different_registers(hdr, obj, disp_hdr);
NearLabel done; NearLabel done;
verify_oop(obj); verify_oop(obj, FILE_AND_LINE);
// Load object header. // Load object header.
z_lg(hdr, Address(obj, hdr_offset)); z_lg(hdr, Address(obj, hdr_offset));
@ -158,7 +158,7 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
// Load object. // Load object.
z_lg(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); z_lg(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
} }
verify_oop(obj); verify_oop(obj, FILE_AND_LINE);
// Test if object header is pointing to the displaced header, and if so, restore // Test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object. If the object header is not pointing to // the displaced header in the object. If the object header is not pointing to
// the displaced header, get the object header instead. // the displaced header, get the object header instead.
@ -278,7 +278,7 @@ void C1_MacroAssembler::initialize_object(
// call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id))); // call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id)));
// } // }
verify_oop(obj); verify_oop(obj, FILE_AND_LINE);
} }
void C1_MacroAssembler::allocate_array( void C1_MacroAssembler::allocate_array(
@ -336,16 +336,15 @@ void C1_MacroAssembler::allocate_array(
// call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id))); // call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id)));
// } // }
verify_oop(obj); verify_oop(obj, FILE_AND_LINE);
} }
#ifndef PRODUCT #ifndef PRODUCT
void C1_MacroAssembler::verify_stack_oop(int stack_offset) { void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
Unimplemented(); if (!VerifyOops) return;
// if (!VerifyOops) return; verify_oop_addr(Address(Z_SP, stack_offset), FILE_AND_LINE);
// verify_oop_addr(Address(SP, stack_offset + STACK_BIAS));
} }
void C1_MacroAssembler::verify_not_null_oop(Register r) { void C1_MacroAssembler::verify_not_null_oop(Register r) {
@ -354,7 +353,7 @@ void C1_MacroAssembler::verify_not_null_oop(Register r) {
compareU64_and_branch(r, (intptr_t)0, bcondNotEqual, not_null); compareU64_and_branch(r, (intptr_t)0, bcondNotEqual, not_null);
stop("non-null oop required"); stop("non-null oop required");
bind(not_null); bind(not_null);
verify_oop(r); verify_oop(r, FILE_AND_LINE);
} }
void C1_MacroAssembler::invalidate_registers(Register preserve1, void C1_MacroAssembler::invalidate_registers(Register preserve1,

View file

@ -339,7 +339,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
oop_maps->add_gc_map(call_offset, map); oop_maps->add_gc_map(call_offset, map);
restore_live_registers_except_r2(sasm); restore_live_registers_except_r2(sasm);
__ verify_oop(obj); __ verify_oop(obj, FILE_AND_LINE);
__ z_br(Z_R14); __ z_br(Z_R14);
} }
break; break;
@ -405,7 +405,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
oop_maps->add_gc_map(call_offset, map); oop_maps->add_gc_map(call_offset, map);
restore_live_registers_except_r2(sasm); restore_live_registers_except_r2(sasm);
__ verify_oop(obj); __ verify_oop(obj, FILE_AND_LINE);
__ z_br(Z_R14); __ z_br(Z_R14);
} }
break; break;
@ -423,7 +423,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
restore_live_registers_except_r2(sasm); restore_live_registers_except_r2(sasm);
// Z_R2,: new multi array // Z_R2,: new multi array
__ verify_oop(Z_R2); __ verify_oop(Z_R2, FILE_AND_LINE);
__ z_br(Z_R14); __ z_br(Z_R14);
} }
break; break;

View file

@ -400,11 +400,11 @@ void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value
__ z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag. __ z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag.
__ z_braz(Lnot_weak); __ z_braz(Lnot_weak);
__ verify_oop(value); __ verify_oop(value, FILE_AND_LINE);
DecoratorSet decorators = IN_NATIVE | ON_PHANTOM_OOP_REF; DecoratorSet decorators = IN_NATIVE | ON_PHANTOM_OOP_REF;
g1_write_barrier_pre(masm, decorators, (const Address*)NULL, value, noreg, tmp1, tmp2, true); g1_write_barrier_pre(masm, decorators, (const Address*)NULL, value, noreg, tmp1, tmp2, true);
__ bind(Lnot_weak); __ bind(Lnot_weak);
__ verify_oop(value); __ verify_oop(value, FILE_AND_LINE);
__ bind(Ldone); __ bind(Ldone);
} }

View file

@ -108,7 +108,7 @@ void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
__ z_nill(value, ~JNIHandles::weak_tag_mask); __ z_nill(value, ~JNIHandles::weak_tag_mask);
__ z_lg(value, 0, value); // Resolve (untagged) jobject. __ z_lg(value, 0, value); // Resolve (untagged) jobject.
__ verify_oop(value); __ verify_oop(value, FILE_AND_LINE);
__ bind(Ldone); __ bind(Ldone);
} }

View file

@ -1664,7 +1664,7 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, Address mdo_addr,
compareU64_and_branch(obj, (intptr_t)0, Assembler::bcondEqual, null_seen); compareU64_and_branch(obj, (intptr_t)0, Assembler::bcondEqual, null_seen);
} }
verify_oop(obj); MacroAssembler::verify_oop(obj, FILE_AND_LINE);
load_klass(klass, obj); load_klass(klass, obj);
// Klass seen before, nothing to do (regardless of unknown bit). // Klass seen before, nothing to do (regardless of unknown bit).
@ -2073,7 +2073,7 @@ void InterpreterMacroAssembler::access_local_int(Register index, Register dst) {
} }
void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) {
if (state == atos) { MacroAssembler::verify_oop(reg); } if (state == atos) { MacroAssembler::verify_oop(reg, FILE_AND_LINE); }
} }
// Inline assembly for: // Inline assembly for:

View file

@ -3587,7 +3587,7 @@ void MacroAssembler::get_vm_result(Register oop_result) {
z_lg(oop_result, Address(Z_thread, JavaThread::vm_result_offset())); z_lg(oop_result, Address(Z_thread, JavaThread::vm_result_offset()));
clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(void*)); clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(void*));
verify_oop(oop_result); verify_oop(oop_result, FILE_AND_LINE);
} }
void MacroAssembler::get_vm_result_2(Register result) { void MacroAssembler::get_vm_result_2(Register result) {
@ -6813,26 +6813,94 @@ void MacroAssembler::verify_thread() {
} }
} }
// Save and restore functions: Exclude Z_R0.
void MacroAssembler::save_volatile_regs(Register dst, int offset, bool include_fp, bool include_flags) {
z_stmg(Z_R1, Z_R5, offset, dst); offset += 5 * BytesPerWord;
if (include_fp) {
z_std(Z_F0, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F1, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F2, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F3, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F4, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F5, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F6, Address(dst, offset)); offset += BytesPerWord;
z_std(Z_F7, Address(dst, offset)); offset += BytesPerWord;
}
if (include_flags) {
Label done;
z_mvi(Address(dst, offset), 2); // encoding: equal
z_bre(done);
z_mvi(Address(dst, offset), 4); // encoding: higher
z_brh(done);
z_mvi(Address(dst, offset), 1); // encoding: lower
bind(done);
}
}
void MacroAssembler::restore_volatile_regs(Register src, int offset, bool include_fp, bool include_flags) {
z_lmg(Z_R1, Z_R5, offset, src); offset += 5 * BytesPerWord;
if (include_fp) {
z_ld(Z_F0, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F1, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F2, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F3, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F4, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F5, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F6, Address(src, offset)); offset += BytesPerWord;
z_ld(Z_F7, Address(src, offset)); offset += BytesPerWord;
}
if (include_flags) {
z_cli(Address(src, offset), 2); // see encoding above
}
}
// Plausibility check for oops. // Plausibility check for oops.
void MacroAssembler::verify_oop(Register oop, const char* msg) { void MacroAssembler::verify_oop(Register oop, const char* msg) {
if (!VerifyOops) return; if (!VerifyOops) return;
BLOCK_COMMENT("verify_oop {"); BLOCK_COMMENT("verify_oop {");
Register tmp = Z_R0; unsigned int nbytes_save = (5 + 8 + 1) * BytesPerWord;
unsigned int nbytes_save = 5*BytesPerWord; address entry_addr = StubRoutines::verify_oop_subroutine_entry_address();
address entry = StubRoutines::verify_oop_subroutine_entry_address();
save_return_pc(); save_return_pc();
push_frame_abi160(nbytes_save);
z_stmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP);
z_lgr(Z_ARG2, oop); // Push frame, but preserve flags
load_const(Z_ARG1, (address) msg); z_lgr(Z_R0, Z_SP);
load_const(Z_R1, entry); z_lay(Z_SP, -((int64_t)nbytes_save + frame::z_abi_160_size), Z_SP);
z_stg(Z_R0, _z_abi(callers_sp), Z_SP);
save_volatile_regs(Z_SP, frame::z_abi_160_size, true, true);
lgr_if_needed(Z_ARG2, oop);
load_const_optimized(Z_ARG1, (address)msg);
load_const_optimized(Z_R1, entry_addr);
z_lg(Z_R1, 0, Z_R1); z_lg(Z_R1, 0, Z_R1);
call_c(Z_R1); call_c(Z_R1);
z_lmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP); restore_volatile_regs(Z_SP, frame::z_abi_160_size, true, true);
pop_frame();
restore_return_pc();
BLOCK_COMMENT("} verify_oop ");
}
void MacroAssembler::verify_oop_addr(Address addr, const char* msg) {
if (!VerifyOops) return;
BLOCK_COMMENT("verify_oop {");
unsigned int nbytes_save = (5 + 8) * BytesPerWord;
address entry_addr = StubRoutines::verify_oop_subroutine_entry_address();
save_return_pc();
unsigned int frame_size = push_frame_abi160(nbytes_save); // kills Z_R0
save_volatile_regs(Z_SP, frame::z_abi_160_size, true, false);
z_lg(Z_ARG2, addr.plus_disp(frame_size));
load_const_optimized(Z_ARG1, (address)msg);
load_const_optimized(Z_R1, entry_addr);
z_lg(Z_R1, 0, Z_R1);
call_c(Z_R1);
restore_volatile_regs(Z_SP, frame::z_abi_160_size, true, false);
pop_frame(); pop_frame();
restore_return_pc(); restore_return_pc();

View file

@ -973,8 +973,15 @@ class MacroAssembler: public Assembler {
// Verify Z_thread contents. // Verify Z_thread contents.
void verify_thread(); void verify_thread();
// Save and restore functions: Exclude Z_R0.
void save_volatile_regs( Register dst, int offset, bool include_fp, bool include_flags);
void restore_volatile_regs(Register src, int offset, bool include_fp, bool include_flags);
// Only if +VerifyOops. // Only if +VerifyOops.
// Kills Z_R0.
void verify_oop(Register reg, const char* s = "broken oop"); void verify_oop(Register reg, const char* s = "broken oop");
// Kills Z_R0, condition code.
void verify_oop_addr(Address addr, const char* msg = "contains broken oop");
// TODO: verify_method and klass metadata (compare against vptr?). // TODO: verify_method and klass metadata (compare against vptr?).
void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {}

View file

@ -85,7 +85,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
BLOCK_COMMENT("verify_klass {"); BLOCK_COMMENT("verify_klass {");
__ verify_oop(obj_reg); __ verify_oop(obj_reg, FILE_AND_LINE);
__ compareU64_and_branch(obj_reg, (intptr_t)0L, Assembler::bcondEqual, L_bad); __ compareU64_and_branch(obj_reg, (intptr_t)0L, Assembler::bcondEqual, L_bad);
__ load_klass(temp_reg, obj_reg); __ load_klass(temp_reg, obj_reg);
// klass_addr is a klass in allstatic SystemDictionaryHandles. Can't get GCed. // klass_addr is a klass in allstatic SystemDictionaryHandles. Can't get GCed.
@ -194,22 +194,22 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
BLOCK_COMMENT("jump_to_lambda_form {"); BLOCK_COMMENT("jump_to_lambda_form {");
// Load the invoker, as MH -> MH.form -> LF.vmentry // Load the invoker, as MH -> MH.form -> LF.vmentry
__ verify_oop(recv); __ verify_oop(recv, FILE_AND_LINE);
__ load_heap_oop(method_temp, __ load_heap_oop(method_temp,
Address(recv, Address(recv,
NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())),
noreg, noreg, IS_NOT_NULL); noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp); __ verify_oop(method_temp, FILE_AND_LINE);
__ load_heap_oop(method_temp, __ load_heap_oop(method_temp,
Address(method_temp, Address(method_temp,
NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())),
noreg, noreg, IS_NOT_NULL); noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp); __ verify_oop(method_temp, FILE_AND_LINE);
__ load_heap_oop(method_temp, __ load_heap_oop(method_temp,
Address(method_temp, Address(method_temp,
NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())),
noreg, noreg, IS_NOT_NULL); noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp); __ verify_oop(method_temp, FILE_AND_LINE);
__ z_lg(method_temp, __ z_lg(method_temp,
Address(method_temp, Address(method_temp,
NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
@ -385,7 +385,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
Register temp1_recv_klass = temp1; Register temp1_recv_klass = temp1;
if (iid != vmIntrinsics::_linkToStatic) { if (iid != vmIntrinsics::_linkToStatic) {
__ verify_oop(receiver_reg); __ verify_oop(receiver_reg, FILE_AND_LINE);
if (iid == vmIntrinsics::_linkToSpecial) { if (iid == vmIntrinsics::_linkToSpecial) {
// Don't actually load the klass; just null-check the receiver. // Don't actually load the klass; just null-check the receiver.
__ null_check(receiver_reg); __ null_check(receiver_reg);

View file

@ -892,9 +892,9 @@ static void verify_oop_args(MacroAssembler *masm,
if (r->is_stack()) { if (r->is_stack()) {
__ z_lg(Z_R0_scratch, __ z_lg(Z_R0_scratch,
Address(Z_SP, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); Address(Z_SP, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize));
__ verify_oop(Z_R0_scratch); __ verify_oop(Z_R0_scratch, FILE_AND_LINE);
} else { } else {
__ verify_oop(r->as_Register()); __ verify_oop(r->as_Register(), FILE_AND_LINE);
} }
} }
} }
@ -2686,7 +2686,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ z_ltgr(Z_ARG1, Z_ARG1); __ z_ltgr(Z_ARG1, Z_ARG1);
__ z_bre(ic_miss); __ z_bre(ic_miss);
} }
__ verify_oop(Z_ARG1); __ verify_oop(Z_ARG1, FILE_AND_LINE);
// Check ic: object class <-> cached class // Check ic: object class <-> cached class
// Compress cached class for comparison. That's more efficient. // Compress cached class for comparison. That's more efficient.
@ -2955,7 +2955,7 @@ void SharedRuntime::generate_deopt_blob() {
#ifdef ASSERT #ifdef ASSERT
// verify that there is really an exception oop in JavaThread // verify that there is really an exception oop in JavaThread
__ z_lg(Z_ARG1, Address(Z_thread, JavaThread::exception_oop_offset())); __ z_lg(Z_ARG1, Address(Z_thread, JavaThread::exception_oop_offset()));
__ verify_oop(Z_ARG1); __ MacroAssembler::verify_oop(Z_ARG1, FILE_AND_LINE);
// verify that there is no pending exception // verify that there is no pending exception
__ asm_assert_mem8_is_zero(in_bytes(Thread::pending_exception_offset()), Z_thread, __ asm_assert_mem8_is_zero(in_bytes(Thread::pending_exception_offset()), Z_thread,

View file

@ -667,6 +667,17 @@ class StubGenerator: public StubCodeGenerator {
return start; return start;
} }
#if !defined(PRODUCT)
// Wrapper which calls oopDesc::is_oop_or_null()
// Only called by MacroAssembler::verify_oop
static void verify_oop_helper(const char* message, oopDesc* o) {
if (!oopDesc::is_oop_or_null(o)) {
fatal("%s. oop: " PTR_FORMAT, message, p2i(o));
}
++ StubRoutines::_verify_oop_count;
}
#endif
// Return address of code to be called from code generated by // Return address of code to be called from code generated by
// MacroAssembler::verify_oop. // MacroAssembler::verify_oop.
// //
@ -679,6 +690,11 @@ class StubGenerator: public StubCodeGenerator {
// StubCodeMark mark(this, "StubRoutines", "verify_oop_stub"); // StubCodeMark mark(this, "StubRoutines", "verify_oop_stub");
address start = 0; address start = 0;
#if !defined(PRODUCT)
start = CAST_FROM_FN_PTR(address, verify_oop_helper);
#endif
return start; return start;
} }

View file

@ -30,6 +30,8 @@
#include "code/nativeInst.hpp" #include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp" #include "code/vtableStubs.hpp"
#include "gc/shared/gcLocker.hpp" #include "gc/shared/gcLocker.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"

View file

@ -51,7 +51,15 @@ void DebugInfoWriteStream::write_metadata(Metadata* h) {
} }
oop DebugInfoReadStream::read_oop() { oop DebugInfoReadStream::read_oop() {
oop o = code()->oop_at(read_int()); nmethod* nm = const_cast<CompiledMethod*>(code())->as_nmethod_or_null();
oop o;
if (nm != NULL) {
// Despite these oops being found inside nmethods that are on-stack,
// they are not kept alive by all GCs (e.g. G1 and Shenandoah).
o = nm->oop_at_phantom(read_int());
} else {
o = code()->oop_at(read_int());
}
assert(oopDesc::is_oop_or_null(o), "oop only"); assert(oopDesc::is_oop_or_null(o), "oop only");
return o; return o;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Red Hat, Inc. All rights reserved. * Copyright (c) 2015, 2020, Red Hat, Inc. All rights reserved.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License version 2 only, as
@ -226,6 +226,7 @@ private:
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahCodeCacheRoots<ITR> _code_roots; ShenandoahCodeCacheRoots<ITR> _code_roots;
ShenandoahVMRoots<false /*concurrent*/ > _vm_roots; ShenandoahVMRoots<false /*concurrent*/ > _vm_roots;
ShenandoahStringDedupRoots _dedup_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots; _cld_roots;
public: public:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Red Hat, Inc. All rights reserved. * Copyright (c) 2019, 2020, Red Hat, Inc. All rights reserved.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License version 2 only, as
@ -250,6 +250,9 @@ void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDC
if (code != NULL && !ShenandoahConcurrentScanCodeRoots) { if (code != NULL && !ShenandoahConcurrentScanCodeRoots) {
_code_roots.code_blobs_do(code, worker_id); _code_roots.code_blobs_do(code, worker_id);
} }
AlwaysTrueClosure always_true;
_dedup_roots.oops_do(&always_true, oops, worker_id);
} }
template <typename ITR> template <typename ITR>

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License version 2 only, as
@ -193,9 +193,6 @@ public:
} else { } else {
_rp->roots_do(worker_id, &roots_cl, &cld_cl, &code_cl); _rp->roots_do(worker_id, &roots_cl, &cld_cl, &code_cl);
} }
AlwaysTrueClosure is_alive;
_dedup_roots.oops_do(&is_alive, &roots_cl, worker_id);
} }
} }
}; };

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it This code is free software; you can redistribute it and/or modify it
@ -1023,36 +1023,6 @@
<Field type="ulong" contentType="bytes" name="size" label="Size Written" /> <Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event> </Event>
<Event name="FlushStorage" category="Flight Recorder" label="Flush Storage" thread="false" experimental="true">
<Field type="ulong" name="flushId" label="Flush Identifier" relation="FlushId" />
<Field type="ulong" name="elements" label="Elements Written" />
<Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event>
<Event name="FlushStacktrace" category="Flight Recorder" label="Flush Stacktrace" thread="false" experimental="true">
<Field type="ulong" name="flushId" label="Flush Identifier" relation="FlushId" />
<Field type="ulong" name="elements" label="Elements Written" />
<Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event>
<Event name="FlushStringPool" category="Flight Recorder" label="Flush String Pool" thread="false" experimental="true">
<Field type="ulong" name="flushId" label="Flush Identifier" relation="FlushId" />
<Field type="ulong" name="elements" label="Elements Written" />
<Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event>
<Event name="FlushMetadata" category="Flight Recorder" label="Flush Metadata" thread="false" experimental="true">
<Field type="ulong" name="flushId" label="Flush Identifier" relation="FlushId" />
<Field type="ulong" name="elements" label="Elements Written" />
<Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event>
<Event name="FlushTypeSet" category="Flight Recorder" label="Flush Type Set" thread="false" experimental="true">
<Field type="ulong" name="flushId" label="Flush Identifier" relation="FlushId" />
<Field type="ulong" name="elements" label="Elements Written" />
<Field type="ulong" contentType="bytes" name="size" label="Size Written" />
</Event>
<Type name="DeoptimizationReason" label="Deoptimization Reason"> <Type name="DeoptimizationReason" label="Deoptimization Reason">
<Field type="string" name="reason" label="Reason" /> <Field type="string" name="reason" label="Reason" />
</Type> </Type>

View file

@ -58,13 +58,12 @@
// incremented on each flushpoint // incremented on each flushpoint
static u8 flushpoint_id = 0; static u8 flushpoint_id = 0;
template <typename E, typename Instance, size_t(Instance::*func)()> template <typename Instance, size_t(Instance::*func)()>
class Content { class Content {
private: private:
Instance& _instance; Instance& _instance;
u4 _elements; u4 _elements;
public: public:
typedef E EventType;
Content(Instance& instance) : _instance(instance), _elements(0) {} Content(Instance& instance) : _instance(instance), _elements(0) {}
bool process() { bool process() {
_elements = (u4)(_instance.*func)(); _elements = (u4)(_instance.*func)();
@ -82,7 +81,6 @@ class WriteContent : public StackObj {
Content& _content; Content& _content;
const int64_t _start_offset; const int64_t _start_offset;
public: public:
typedef typename Content::EventType EventType;
WriteContent(JfrChunkWriter& cw, Content& content) : WriteContent(JfrChunkWriter& cw, Content& content) :
_start_time(JfrTicks::now()), _start_time(JfrTicks::now()),
@ -128,14 +126,6 @@ class WriteContent : public StackObj {
return (u4)(end_offset() - start_offset()); return (u4)(end_offset() - start_offset());
} }
static bool is_event_enabled() {
return EventType::is_enabled();
}
static u8 event_id() {
return EventType::eventId;
}
void write_elements(int64_t offset) { void write_elements(int64_t offset) {
_cw.write_padded_at_offset<u4>(elements(), offset); _cw.write_padded_at_offset<u4>(elements(), offset);
} }
@ -198,23 +188,16 @@ static u4 invoke(Functor& f) {
return f.elements(); return f.elements();
} }
template <typename Functor>
static void write_flush_event(Functor& f) {
if (Functor::is_event_enabled()) {
typename Functor::EventType e(UNTIMED);
e.set_starttime(f.start_time());
e.set_endtime(f.end_time());
e.set_flushId(flushpoint_id);
e.set_elements(f.elements());
e.set_size(f.size());
e.commit();
}
}
template <typename Functor> template <typename Functor>
static u4 invoke_with_flush_event(Functor& f) { static u4 invoke_with_flush_event(Functor& f) {
const u4 elements = invoke(f); const u4 elements = invoke(f);
write_flush_event(f); EventFlush e(UNTIMED);
e.set_starttime(f.start_time());
e.set_endtime(f.end_time());
e.set_flushId(flushpoint_id);
e.set_elements(f.elements());
e.set_size(f.size());
e.commit();
return elements; return elements;
} }
@ -226,7 +209,6 @@ class StackTraceRepository : public StackObj {
bool _clear; bool _clear;
public: public:
typedef EventFlushStacktrace EventType;
StackTraceRepository(JfrStackTraceRepository& repo, JfrChunkWriter& cw, bool clear) : StackTraceRepository(JfrStackTraceRepository& repo, JfrChunkWriter& cw, bool clear) :
_repo(repo), _cw(cw), _elements(0), _clear(clear) {} _repo(repo), _cw(cw), _elements(0), _clear(clear) {}
bool process() { bool process() {
@ -242,7 +224,7 @@ typedef WriteCheckpointEvent<StackTraceRepository> WriteStackTrace;
static u4 flush_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter) { static u4 flush_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter) {
StackTraceRepository str(stack_trace_repo, chunkwriter, false); StackTraceRepository str(stack_trace_repo, chunkwriter, false);
WriteStackTrace wst(chunkwriter, str, TYPE_STACKTRACE); WriteStackTrace wst(chunkwriter, str, TYPE_STACKTRACE);
return invoke_with_flush_event(wst); return invoke(wst);
} }
static u4 write_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) { static u4 write_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWriter& chunkwriter, bool clear) {
@ -251,14 +233,14 @@ static u4 write_stacktrace(JfrStackTraceRepository& stack_trace_repo, JfrChunkWr
return invoke(wst); return invoke(wst);
} }
typedef Content<EventFlushStorage, JfrStorage, &JfrStorage::write> Storage; typedef Content<JfrStorage, &JfrStorage::write> Storage;
typedef WriteContent<Storage> WriteStorage; typedef WriteContent<Storage> WriteStorage;
static size_t flush_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) { static size_t flush_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) {
assert(chunkwriter.is_valid(), "invariant"); assert(chunkwriter.is_valid(), "invariant");
Storage fsf(storage); Storage fsf(storage);
WriteStorage fs(chunkwriter, fsf); WriteStorage fs(chunkwriter, fsf);
return invoke_with_flush_event(fs); return invoke(fs);
} }
static size_t write_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) { static size_t write_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) {
@ -268,15 +250,15 @@ static size_t write_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) {
return invoke(fs); return invoke(fs);
} }
typedef Content<EventFlushStringPool, JfrStringPool, &JfrStringPool::write> StringPool; typedef Content<JfrStringPool, &JfrStringPool::write> StringPool;
typedef Content<EventFlushStringPool, JfrStringPool, &JfrStringPool::write_at_safepoint> StringPoolSafepoint; typedef Content<JfrStringPool, &JfrStringPool::write_at_safepoint> StringPoolSafepoint;
typedef WriteCheckpointEvent<StringPool> WriteStringPool; typedef WriteCheckpointEvent<StringPool> WriteStringPool;
typedef WriteCheckpointEvent<StringPoolSafepoint> WriteStringPoolSafepoint; typedef WriteCheckpointEvent<StringPoolSafepoint> WriteStringPoolSafepoint;
static u4 flush_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { static u4 flush_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
StringPool sp(string_pool); StringPool sp(string_pool);
WriteStringPool wsp(chunkwriter, sp, TYPE_STRING); WriteStringPool wsp(chunkwriter, sp, TYPE_STRING);
return invoke_with_flush_event(wsp); return invoke(wsp);
} }
static u4 write_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) { static u4 write_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
@ -291,20 +273,19 @@ static u4 write_stringpool_safepoint(JfrStringPool& string_pool, JfrChunkWriter&
return invoke(wsps); return invoke(wsps);
} }
typedef Content<EventFlushTypeSet, JfrCheckpointManager, &JfrCheckpointManager::flush_type_set> FlushTypeSetFunctor; typedef Content<JfrCheckpointManager, &JfrCheckpointManager::flush_type_set> FlushTypeSetFunctor;
typedef WriteContent<FlushTypeSetFunctor> FlushTypeSet; typedef WriteContent<FlushTypeSetFunctor> FlushTypeSet;
static u4 flush_typeset(JfrCheckpointManager& checkpoint_manager, JfrChunkWriter& chunkwriter) { static u4 flush_typeset(JfrCheckpointManager& checkpoint_manager, JfrChunkWriter& chunkwriter) {
FlushTypeSetFunctor flush_type_set(checkpoint_manager); FlushTypeSetFunctor flush_type_set(checkpoint_manager);
FlushTypeSet fts(chunkwriter, flush_type_set); FlushTypeSet fts(chunkwriter, flush_type_set);
return invoke_with_flush_event(fts); return invoke(fts);
} }
class MetadataEvent : public StackObj { class MetadataEvent : public StackObj {
private: private:
JfrChunkWriter& _cw; JfrChunkWriter& _cw;
public: public:
typedef EventFlushMetadata EventType;
MetadataEvent(JfrChunkWriter& cw) : _cw(cw) {} MetadataEvent(JfrChunkWriter& cw) : _cw(cw) {}
bool process() { bool process() {
JfrMetadataEvent::write(_cw); JfrMetadataEvent::write(_cw);
@ -319,7 +300,7 @@ static u4 flush_metadata(JfrChunkWriter& chunkwriter) {
assert(chunkwriter.is_valid(), "invariant"); assert(chunkwriter.is_valid(), "invariant");
MetadataEvent me(chunkwriter); MetadataEvent me(chunkwriter);
WriteMetadata wm(chunkwriter, me); WriteMetadata wm(chunkwriter, me);
return invoke_with_flush_event(wm); return invoke(wm);
} }
static u4 write_metadata(JfrChunkWriter& chunkwriter) { static u4 write_metadata(JfrChunkWriter& chunkwriter) {
@ -651,7 +632,7 @@ size_t JfrRecorderService::flush() {
return total_elements; return total_elements;
} }
typedef Content<EventFlush, JfrRecorderService, &JfrRecorderService::flush> FlushFunctor; typedef Content<JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
typedef WriteContent<FlushFunctor> Flush; typedef WriteContent<FlushFunctor> Flush;
void JfrRecorderService::invoke_flush() { void JfrRecorderService::invoke_flush() {

View file

@ -1048,11 +1048,11 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi,
// if there is a higher range, test for it and process it: // if there is a higher range, test for it and process it:
if (mid < hi && !eq_test_only) { if (mid < hi && !eq_test_only) {
// two comparisons of same values--should enable 1 test for 2 branches // two comparisons of same values--should enable 1 test for 2 branches
// Use BoolTest::le instead of BoolTest::gt // Use BoolTest::lt instead of BoolTest::gt
float cnt = sum_of_cnts(lo, mid-1); float cnt = sum_of_cnts(lo, mid-1);
IfNode *iff_le = jump_if_fork_int(key_val, test_val, BoolTest::le, if_prob(cnt, total_cnt), if_cnt(cnt)); IfNode *iff_lt = jump_if_fork_int(key_val, test_val, BoolTest::lt, if_prob(cnt, total_cnt), if_cnt(cnt));
Node *iftrue = _gvn.transform( new IfTrueNode(iff_le) ); Node *iftrue = _gvn.transform( new IfTrueNode(iff_lt) );
Node *iffalse = _gvn.transform( new IfFalseNode(iff_le) ); Node *iffalse = _gvn.transform( new IfFalseNode(iff_lt) );
{ PreserveJVMState pjvms(this); { PreserveJVMState pjvms(this);
set_control(iffalse); set_control(iffalse);
jump_switch_ranges(key_val, mid+1, hi, switch_depth+1); jump_switch_ranges(key_val, mid+1, hi, switch_depth+1);

View file

@ -108,8 +108,8 @@ template <typename T> struct CountLeadingZerosImpl<T, 4> {
template <typename T> struct CountLeadingZerosImpl<T, 8> { template <typename T> struct CountLeadingZerosImpl<T, 8> {
static unsigned doit(T v) { static unsigned doit(T v) {
unsigned long index;
#ifdef _LP64 #ifdef _LP64
unsigned long index;
_BitScanReverse64(&index, v); _BitScanReverse64(&index, v);
return 63u - index; return 63u - index;
#else #else

View file

@ -89,16 +89,15 @@ import sun.reflect.annotation.*;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
/** /**
* Instances of the class {@code Class} represent classes and interfaces * Instances of the class {@code Class} represent classes and
* in a running Java application. An enum type is a kind of class and an * interfaces in a running Java application. An enum type and a record
* annotation type is a kind of interface. Every array also * type are kinds of class; an annotation type is a kind of
* belongs to a class that is reflected as a {@code Class} object * interface. Every array also belongs to a class that is reflected as
* that is shared by all arrays with the same element type and number * a {@code Class} object that is shared by all arrays with the same
* of dimensions. The primitive Java types ({@code boolean}, * element type and number of dimensions. The primitive Java types
* {@code byte}, {@code char}, {@code short}, * ({@code boolean}, {@code byte}, {@code char}, {@code short}, {@code
* {@code int}, {@code long}, {@code float}, and * int}, {@code long}, {@code float}, and {@code double}), and the
* {@code double}), and the keyword {@code void} are also * keyword {@code void} are also represented as {@code Class} objects.
* represented as {@code Class} objects.
* *
* <p> {@code Class} has no public constructor. Instead a {@code Class} * <p> {@code Class} has no public constructor. Instead a {@code Class}
* object is constructed automatically by the Java Virtual Machine * object is constructed automatically by the Java Virtual Machine

View file

@ -71,7 +71,8 @@ package java.lang.annotation;
* @jls 4.1 The Kinds of Types and Values * @jls 4.1 The Kinds of Types and Values
*/ */
public enum ElementType { public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */ /** Class, interface (including annotation type), enum, or record
* declaration */
TYPE, TYPE,
/** Field declaration (includes enum constants) */ /** Field declaration (includes enum constants) */

View file

@ -1451,7 +1451,7 @@ public class MethodHandles {
* <li>If the new lookup class is in the same module as the old lookup class, * <li>If the new lookup class is in the same module as the old lookup class,
* the new previous lookup class is the old previous lookup class. * the new previous lookup class is the old previous lookup class.
* <li>If the new lookup class is in a different module from the old lookup class, * <li>If the new lookup class is in a different module from the old lookup class,
* the new previous lookup class is the the old lookup class. * the new previous lookup class is the old lookup class.
*</ul> *</ul>
* <p> * <p>
* The resulting lookup's capabilities for loading classes * The resulting lookup's capabilities for loading classes

View file

@ -2579,7 +2579,7 @@ public class Flow {
recordExit(exit); recordExit(exit);
return ; return ;
} else { } else {
scan(tree.value); scanExpr(tree.value);
recordExit(new AssignPendingExit(tree, inits, uninits)); recordExit(new AssignPendingExit(tree, inits, uninits));
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3746,7 +3746,7 @@ public class JavacParser implements Parser {
ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>(); ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
for (JCVariableDecl param : headerFields) { for (JCVariableDecl param : headerFields) {
tmpParams.add(F.at(param) tmpParams.add(F.at(param)
.VarDef(F.Modifiers(Flags.PARAMETER | param.mods.flags & Flags.VARARGS | param.mods.flags & Flags.FINAL), .VarDef(F.Modifiers(Flags.PARAMETER | param.mods.flags & Flags.VARARGS),
param.name, param.vartype, null)); param.name, param.vartype, null));
} }
methDef.params = tmpParams.toList(); methDef.params = tmpParams.toList();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -58,13 +58,6 @@ import java.util.zip.ZipFile;
* a .class file, a directory, or a JAR file. * a .class file, a directory, or a JAR file.
*/ */
public class ClassFileReader implements Closeable { public class ClassFileReader implements Closeable {
/**
* Returns a ClassFileReader instance of a given path.
*/
public static ClassFileReader newInstance(Path path) throws IOException {
return newInstance(path, null);
}
/** /**
* Returns a ClassFileReader instance of a given path. * Returns a ClassFileReader instance of a given path.
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -915,6 +915,11 @@ class JdepsTask {
option); option);
return false; return false;
} }
if (!options.rootModules.isEmpty()) {
reportError("err.invalid.options", "-m or --module",
option);
return false;
}
return true; return true;
} }
@ -922,12 +927,12 @@ class JdepsTask {
boolean run(JdepsConfiguration config) throws IOException { boolean run(JdepsConfiguration config) throws IOException {
// check if any JAR file contains unnamed package // check if any JAR file contains unnamed package
for (String arg : inputArgs) { for (String arg : inputArgs) {
try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) { try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg), config.getVersion())) {
Optional<String> classInUnnamedPackage = Optional<String> classInUnnamedPackage =
reader.entries().stream() reader.entries().stream()
.filter(n -> n.endsWith(".class")) .filter(n -> n.endsWith(".class"))
.filter(cn -> toPackageName(cn).isEmpty()) .filter(cn -> toPackageName(cn).isEmpty())
.findFirst(); .findFirst();
if (classInUnnamedPackage.isPresent()) { if (classInUnnamedPackage.isPresent()) {
if (classInUnnamedPackage.get().equals("module-info.class")) { if (classInUnnamedPackage.get().equals("module-info.class")) {
@ -942,10 +947,10 @@ class JdepsTask {
ModuleInfoBuilder builder ModuleInfoBuilder builder
= new ModuleInfoBuilder(config, inputArgs, dir, openModule); = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
boolean ok = builder.run(); boolean ok = builder.run(options.ignoreMissingDeps, log, options.nowarning);
if (!ok) {
if (!ok && !options.nowarning) {
reportError("err.missing.dependences"); reportError("err.missing.dependences");
log.println();
builder.visitMissingDeps(new SimpleDepVisitor()); builder.visitMissingDeps(new SimpleDepVisitor());
} }
return ok; return ok;
@ -981,7 +986,7 @@ class JdepsTask {
throw new UncheckedBadArgs(new BadArgs("err.invalid.options", throw new UncheckedBadArgs(new BadArgs("err.invalid.options",
list, "--check")); list, "--check"));
} }
return new ModuleAnalyzer(config, log, modules).run(); return new ModuleAnalyzer(config, log, modules).run(options.ignoreMissingDeps);
} }
/* /*
@ -1041,7 +1046,7 @@ class JdepsTask {
separator); separator);
boolean ok = analyzer.run(options.depth(), options.ignoreMissingDeps); boolean ok = analyzer.run(options.depth(), options.ignoreMissingDeps);
if (!ok) { if (!ok) {
reportError("err.cant.list.module.deps"); reportError("err.missing.dependences");
log.println(); log.println();
analyzer.visitMissingDeps(new SimpleDepVisitor()); analyzer.visitMissingDeps(new SimpleDepVisitor());
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,22 +24,16 @@
*/ */
package com.sun.tools.jdeps; package com.sun.tools.jdeps;
import static com.sun.tools.jdeps.Graph.*;
import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER; import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER;
import static com.sun.tools.jdeps.Module.*; import static com.sun.tools.jdeps.Module.*;
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
import static java.util.stream.Collectors.*; import static java.util.stream.Collectors.*;
import com.sun.tools.classfile.Dependency; import com.sun.tools.classfile.Dependency;
import com.sun.tools.jdeps.JdepsTask.BadArgs;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -80,23 +74,32 @@ public class ModuleAnalyzer {
} }
} }
public boolean run() throws IOException { public boolean run(boolean ignoreMissingDeps) throws IOException {
try { try {
// compute "requires transitive" dependences for (ModuleDeps md: modules.values()) {
modules.values().forEach(ModuleDeps::computeRequiresTransitive); // compute "requires transitive" dependences
md.computeRequiresTransitive(ignoreMissingDeps);
modules.values().forEach(md -> {
// compute "requires" dependences // compute "requires" dependences
md.computeRequires(); md.computeRequires(ignoreMissingDeps);
// print module descriptor
md.printModuleDescriptor();
// apply transitive reduction and reports recommended requires. // apply transitive reduction and reports recommended requires.
md.analyzeDeps(); boolean ok = md.analyzeDeps();
}); if (!ok) return false;
if (ignoreMissingDeps && md.hasMissingDependencies()) {
log.format("Warning: --ignore-missing-deps specified. Missing dependencies from %s are ignored%n",
md.root.name());
}
}
} finally { } finally {
dependencyFinder.shutdown(); dependencyFinder.shutdown();
} }
return true; return true;
} }
class ModuleDeps { class ModuleDeps {
final Module root; final Module root;
Set<Module> requiresTransitive; Set<Module> requiresTransitive;
@ -110,23 +113,22 @@ public class ModuleAnalyzer {
/** /**
* Compute 'requires transitive' dependences by analyzing API dependencies * Compute 'requires transitive' dependences by analyzing API dependencies
*/ */
private void computeRequiresTransitive() { private void computeRequiresTransitive(boolean ignoreMissingDeps) {
// record requires transitive // record requires transitive
this.requiresTransitive = computeRequires(true) this.requiresTransitive = computeRequires(true, ignoreMissingDeps)
.filter(m -> !m.name().equals(JAVA_BASE)) .filter(m -> !m.name().equals(JAVA_BASE))
.collect(toSet()); .collect(toSet());
trace("requires transitive: %s%n", requiresTransitive); trace("requires transitive: %s%n", requiresTransitive);
} }
private void computeRequires() { private void computeRequires(boolean ignoreMissingDeps) {
this.requires = computeRequires(false).collect(toSet()); this.requires = computeRequires(false, ignoreMissingDeps).collect(toSet());
trace("requires: %s%n", requires); trace("requires: %s%n", requires);
} }
private Stream<Module> computeRequires(boolean apionly) { private Stream<Module> computeRequires(boolean apionly, boolean ignoreMissingDeps) {
// analyze all classes // analyze all classes
if (apionly) { if (apionly) {
dependencyFinder.parseExportedAPIs(Stream.of(root)); dependencyFinder.parseExportedAPIs(Stream.of(root));
} else { } else {
@ -135,9 +137,14 @@ public class ModuleAnalyzer {
// find the modules of all the dependencies found // find the modules of all the dependencies found
return dependencyFinder.getDependences(root) return dependencyFinder.getDependences(root)
.filter(a -> !(ignoreMissingDeps && Analyzer.notFound(a)))
.map(Archive::getModule); .map(Archive::getModule);
} }
boolean hasMissingDependencies() {
return dependencyFinder.getDependences(root).anyMatch(Analyzer::notFound);
}
ModuleDescriptor descriptor() { ModuleDescriptor descriptor() {
return descriptor(requiresTransitive, requires); return descriptor(requiresTransitive, requires);
} }
@ -196,12 +203,30 @@ public class ModuleAnalyzer {
return descriptor(requiresTransitive, g.adjacentNodes(root)); return descriptor(requiresTransitive, g.adjacentNodes(root));
} }
private void showMissingDeps() {
// build the analyzer if there are missing dependences
Analyzer analyzer = new Analyzer(configuration, Analyzer.Type.CLASS, DEFAULT_FILTER);
analyzer.run(Set.of(root), dependencyFinder.locationToArchive());
log.println("Error: Missing dependencies: classes not found from the module path.");
Analyzer.Visitor visitor = new Analyzer.Visitor() {
@Override
public void visitDependence(String origin, Archive originArchive, String target, Archive targetArchive) {
log.format(" %-50s -> %-50s %s%n", origin, target, targetArchive.getName());
}
};
analyzer.visitDependences(root, visitor, Analyzer.Type.VERBOSE, Analyzer::notFound);
log.println();
}
/** /**
* Apply transitive reduction on the resulting graph and reports * Apply transitive reduction on the resulting graph and reports
* recommended requires. * recommended requires.
*/ */
private void analyzeDeps() { private boolean analyzeDeps() {
printModuleDescriptor(log, root); if (requires.stream().anyMatch(m -> m == UNNAMED_MODULE)) {
showMissingDeps();
return false;
}
ModuleDescriptor analyzedDescriptor = descriptor(); ModuleDescriptor analyzedDescriptor = descriptor();
if (!matches(root.descriptor(), analyzedDescriptor)) { if (!matches(root.descriptor(), analyzedDescriptor)) {
@ -223,6 +248,7 @@ public class ModuleAnalyzer {
checkQualifiedExports(); checkQualifiedExports();
log.println(); log.println();
return true;
} }
private void checkQualifiedExports() { private void checkQualifiedExports() {
@ -239,6 +265,10 @@ public class ModuleAnalyzer {
.collect(joining(",")))); .collect(joining(","))));
} }
void printModuleDescriptor() {
printModuleDescriptor(log, root);
}
private void printModuleDescriptor(PrintWriter out, Module module) { private void printModuleDescriptor(PrintWriter out, Module module) {
ModuleDescriptor descriptor = module.descriptor(); ModuleDescriptor descriptor = module.descriptor();
out.format("%s (%s)%n", descriptor.name(), module.location()); out.format("%s (%s)%n", descriptor.name(), module.location());

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -98,7 +98,7 @@ public class ModuleInfoBuilder {
} }
} }
public boolean run() throws IOException { public boolean run(boolean ignoreMissingDeps, PrintWriter log, boolean quiet) throws IOException {
try { try {
// pass 1: find API dependencies // pass 1: find API dependencies
Map<Archive, Set<Archive>> requiresTransitive = computeRequiresTransitive(); Map<Archive, Set<Archive>> requiresTransitive = computeRequiresTransitive();
@ -108,52 +108,65 @@ public class ModuleInfoBuilder {
analyzer.run(automaticModules(), dependencyFinder.locationToArchive()); analyzer.run(automaticModules(), dependencyFinder.locationToArchive());
boolean missingDeps = false;
for (Module m : automaticModules()) { for (Module m : automaticModules()) {
Set<Archive> apiDeps = requiresTransitive.containsKey(m) Set<Archive> apiDeps = requiresTransitive.containsKey(m)
? requiresTransitive.get(m) ? requiresTransitive.get(m)
: Collections.emptySet(); : Collections.emptySet();
Path file = outputdir.resolve(m.name()).resolve("module-info.java"); // if this is a multi-release JAR, write to versions/$VERSION/module-info.java
Runtime.Version version = configuration.getVersion();
Path dir = version != null
? outputdir.resolve(m.name())
.resolve("versions")
.resolve(String.valueOf(version.feature()))
: outputdir.resolve(m.name());
Path file = dir.resolve("module-info.java");
// computes requires and requires transitive // computes requires and requires transitive
Module normalModule = toNormalModule(m, apiDeps); Module normalModule = toNormalModule(m, apiDeps, ignoreMissingDeps);
if (normalModule != null) { if (normalModule != null) {
automaticToNormalModule.put(m, normalModule); automaticToNormalModule.put(m, normalModule);
// generate module-info.java // generate module-info.java
System.out.format("writing to %s%n", file); if (!quiet) {
if (ignoreMissingDeps && analyzer.requires(m).anyMatch(Analyzer::notFound)) {
log.format("Warning: --ignore-missing-deps specified. Missing dependencies from %s are ignored%n",
m.name());
}
log.format("writing to %s%n", file);
}
writeModuleInfo(file, normalModule.descriptor()); writeModuleInfo(file, normalModule.descriptor());
} else { } else {
// find missing dependences // find missing dependences
System.out.format("Missing dependence: %s not generated%n", file); return false;
missingDeps = true;
} }
} }
return !missingDeps;
} finally { } finally {
dependencyFinder.shutdown(); dependencyFinder.shutdown();
} }
return true;
} }
private Module toNormalModule(Module module, Set<Archive> requiresTransitive) private Module toNormalModule(Module module, Set<Archive> requiresTransitive, boolean ignoreMissingDeps)
throws IOException throws IOException
{ {
// done analysis // done analysis
module.close(); module.close();
if (analyzer.requires(module).anyMatch(Analyzer::notFound)) { if (!ignoreMissingDeps && analyzer.requires(module).anyMatch(Analyzer::notFound)) {
// missing dependencies // missing dependencies
return null; return null;
} }
Map<String, Boolean> requires = new HashMap<>(); Map<String, Boolean> requires = new HashMap<>();
requiresTransitive.stream() requiresTransitive.stream()
.filter(a -> !(ignoreMissingDeps && Analyzer.notFound(a)))
.map(Archive::getModule) .map(Archive::getModule)
.forEach(m -> requires.put(m.name(), Boolean.TRUE)); .forEach(m -> requires.put(m.name(), Boolean.TRUE));
analyzer.requires(module) analyzer.requires(module)
.filter(a -> !(ignoreMissingDeps && Analyzer.notFound(a)))
.map(Archive::getModule) .map(Archive::getModule)
.forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE)); .forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE));

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -229,7 +229,6 @@ main.opt.multi-release=\
err.command.set={0} and {1} options are specified. err.command.set={0} and {1} options are specified.
err.unknown.option=unknown option: {0} err.unknown.option=unknown option: {0}
err.missing.arg=no value given for {0} err.missing.arg=no value given for {0}
err.missing.dependences=missing dependencies
err.invalid.arg.for.option=invalid argument for option: {0} err.invalid.arg.for.option=invalid argument for option: {0}
err.option.after.class=option must be specified before classes: {0} err.option.after.class=option must be specified before classes: {0}
err.genmoduleinfo.not.jarfile={0} is a modular JAR file that cannot be specified with the --generate-module-info option err.genmoduleinfo.not.jarfile={0} is a modular JAR file that cannot be specified with the --generate-module-info option
@ -246,8 +245,8 @@ err.multirelease.option.exists={0} is not a multi-release jar file but --multi-r
err.multirelease.option.notfound={0} is a multi-release jar file but --multi-release option is not set err.multirelease.option.notfound={0} is a multi-release jar file but --multi-release option is not set
err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2} err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2}
err.multirelease.jar.malformed=malformed multi-release jar, {0}, bad entry: {1} err.multirelease.jar.malformed=malformed multi-release jar, {0}, bad entry: {1}
err.cant.list.module.deps=\ err.missing.dependences=\
Missing dependencies from the module path and classpath.\n\ Missing dependencies: classes not found from the module path and classpath.\n\
To suppress this error, use --ignore-missing-deps to continue. To suppress this error, use --ignore-missing-deps to continue.
warn.invalid.arg=Path does not exist: {0} warn.invalid.arg=Path does not exist: {0}

View file

@ -671,32 +671,7 @@
</event> </event>
<event name="jdk.Flush"> <event name="jdk.Flush">
<setting name="enabled">true</setting> <setting name="enabled">false</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStorage">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStacktrace">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStringPool">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushMetadata">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushTypeSet">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting> <setting name="threshold">0 ns</setting>
</event> </event>

View file

@ -671,32 +671,7 @@
</event> </event>
<event name="jdk.Flush"> <event name="jdk.Flush">
<setting name="enabled">true</setting> <setting name="enabled">false</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStorage">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStacktrace">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushStringPool">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushMetadata">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting>
</event>
<event name="jdk.FlushTypeSet">
<setting name="enabled">true</setting>
<setting name="threshold">0 ns</setting> <setting name="threshold">0 ns</setting>
</event> </event>

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -596,6 +596,7 @@ class Feedback {
INTERFACE("interface declaration"), INTERFACE("interface declaration"),
ENUM("enum declaration"), ENUM("enum declaration"),
ANNOTATION("annotation interface declaration"), ANNOTATION("annotation interface declaration"),
RECORD("record declaration"),
METHOD("method declaration -- note: {type}==parameter-types"), METHOD("method declaration -- note: {type}==parameter-types"),
VARDECL("variable declaration without init"), VARDECL("variable declaration without init"),
VARINIT("variable declaration with init"), VARINIT("variable declaration with init"),

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3324,6 +3324,9 @@ public class JShellTool implements MessageHandler {
case ANNOTATION_TYPE_SUBKIND: case ANNOTATION_TYPE_SUBKIND:
kind = "@interface"; kind = "@interface";
break; break;
case RECORD_SUBKIND:
kind = "record";
break;
default: default:
assert false : "Wrong kind" + ck.subKind(); assert false : "Wrong kind" + ck.subKind();
kind = "class"; kind = "class";
@ -3819,6 +3822,9 @@ public class JShellTool implements MessageHandler {
case ANNOTATION_TYPE_SUBKIND: case ANNOTATION_TYPE_SUBKIND:
custom(FormatCase.ANNOTATION, ((TypeDeclSnippet) sn).name()); custom(FormatCase.ANNOTATION, ((TypeDeclSnippet) sn).name());
break; break;
case RECORD_SUBKIND:
custom(FormatCase.RECORD, ((TypeDeclSnippet) sn).name());
break;
case METHOD_SUBKIND: case METHOD_SUBKIND:
custom(FormatCase.METHOD, ((MethodSnippet) sn).name(), ((MethodSnippet) sn).parameterTypes()); custom(FormatCase.METHOD, ((MethodSnippet) sn).name(), ((MethodSnippet) sn).parameterTypes());
break; break;

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -855,6 +855,7 @@ The case selector kind describes the kind of snippet. The values are:\n\t\
interface -- interface declaration\n\t\ interface -- interface declaration\n\t\
enum -- enum declaration\n\t\ enum -- enum declaration\n\t\
annotation -- annotation interface declaration\n\t\ annotation -- annotation interface declaration\n\t\
record -- record declaration\n\t\
method -- method declaration -- note: {type}==parameter-types\n\t\ method -- method declaration -- note: {type}==parameter-types\n\t\
vardecl -- variable declaration without init\n\t\ vardecl -- variable declaration without init\n\t\
varinit -- variable declaration with init\n\t\ varinit -- variable declaration with init\n\t\
@ -1158,12 +1159,12 @@ startup.feedback = \
/set format verbose action ' update overwrote' overwrote-update \n\ /set format verbose action ' update overwrote' overwrote-update \n\
/set format verbose action ' update dropped' dropped-update \n\ /set format verbose action ' update dropped' dropped-update \n\
\n\ \n\
/set format verbose until ', however, it cannot be instantiated or its methods invoked until' defined-class-primary \n\ /set format verbose until ', however, it cannot be instantiated or its methods invoked until' defined-class,record-primary \n\
/set format verbose until ', however, its methods cannot be invoked until' defined-interface-primary \n\ /set format verbose until ', however, its methods cannot be invoked until' defined-interface-primary \n\
/set format verbose until ', however, it cannot be used until' defined-enum,annotation-primary \n\ /set format verbose until ', however, it cannot be used until' defined-enum,annotation-primary \n\
/set format verbose until ', however, it cannot be invoked until' defined-method-primary \n\ /set format verbose until ', however, it cannot be invoked until' defined-method-primary \n\
/set format verbose until ', however, it cannot be referenced until' notdefined-primary \n\ /set format verbose until ', however, it cannot be referenced until' notdefined-primary \n\
/set format verbose until ' which cannot be instantiated or its methods invoked until' defined-class-update \n\ /set format verbose until ' which cannot be instantiated or its methods invoked until' defined-class,record-update \n\
/set format verbose until ' whose methods cannot be invoked until' defined-interface-update \n\ /set format verbose until ' whose methods cannot be invoked until' defined-interface-update \n\
/set format verbose until ' which cannot be invoked until' defined-method-update \n\ /set format verbose until ' which cannot be invoked until' defined-method-update \n\
/set format verbose until ' which cannot be referenced until' notdefined-update \n\ /set format verbose until ' which cannot be referenced until' notdefined-update \n\
@ -1183,6 +1184,7 @@ startup.feedback = \
/set format verbose typeKind 'interface' interface \n\ /set format verbose typeKind 'interface' interface \n\
/set format verbose typeKind 'enum' enum \n\ /set format verbose typeKind 'enum' enum \n\
/set format verbose typeKind 'annotation interface' annotation \n\ /set format verbose typeKind 'annotation interface' annotation \n\
/set format verbose typeKind 'record' record \n\
\n\ \n\
/set format verbose result '{name} ==> {value}{post}' added,modified,replaced-ok-primary \n\ /set format verbose result '{name} ==> {value}{post}' added,modified,replaced-ok-primary \n\
\n\ \n\
@ -1194,10 +1196,10 @@ startup.feedback = \
/set format verbose display '{pre}{action} variable {name}{post}' dropped-vardecl,varinit,expression \n\ /set format verbose display '{pre}{action} variable {name}{post}' dropped-vardecl,varinit,expression \n\
/set format verbose display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\ /set format verbose display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\
\n\ \n\
/set format verbose display '{pre}{action} {typeKind} {name}{resolve}{post}' class,interface,enum,annotation \n\ /set format verbose display '{pre}{action} {typeKind} {name}{resolve}{post}' class,interface,enum,annotation,record \n\
/set format verbose display '{pre}{action} method {name}({type}){resolve}{post}' method \n\ /set format verbose display '{pre}{action} method {name}({type}){resolve}{post}' method \n\
\n\ \n\
/set format verbose display '{pre}attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation \n\ /set format verbose display '{pre}attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation,record \n\
/set format verbose display '{pre}attempted to call method {name}({type}){resolve}{post}' used-method \n\ /set format verbose display '{pre}attempted to call method {name}({type}){resolve}{post}' used-method \n\
\n\ \n\
/set truncation verbose 80\n\ /set truncation verbose 80\n\
@ -1211,7 +1213,7 @@ startup.feedback = \
\n\ \n\
/set prompt concise 'jshell> ' ' ...> ' \n\ /set prompt concise 'jshell> ' ' ...> ' \n\
\n\ \n\
/set format concise display '' class,interface,enum,annotation,method,assignment,varinit,vardecl-ok \n\ /set format concise display '' class,interface,enum,annotation,record,method,assignment,varinit,vardecl-ok \n\
\n\ \n\
/set feedback normal \n\ /set feedback normal \n\
\n\ \n\

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,10 @@ import static com.sun.tools.javac.code.Flags.PUBLIC;
import static com.sun.tools.javac.code.Flags.STATIC; import static com.sun.tools.javac.code.Flags.STATIC;
import static com.sun.tools.javac.code.Flags.INTERFACE; import static com.sun.tools.javac.code.Flags.INTERFACE;
import static com.sun.tools.javac.code.Flags.ENUM; import static com.sun.tools.javac.code.Flags.ENUM;
import static com.sun.tools.javac.code.Flags.RECORD;
import static com.sun.tools.javac.code.Flags.SYNTHETIC;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.tree.TreeInfo;
import jdk.jshell.Wrap.CompoundWrap; import jdk.jshell.Wrap.CompoundWrap;
import jdk.jshell.Wrap.Range; import jdk.jshell.Wrap.Range;
import jdk.jshell.Wrap.RangeWrap; import jdk.jshell.Wrap.RangeWrap;
@ -114,6 +118,7 @@ class Corraller extends Visitor {
public void visitClassDef(JCClassDecl tree) { public void visitClassDef(JCClassDecl tree) {
boolean isEnum = (tree.mods.flags & ENUM) != 0; boolean isEnum = (tree.mods.flags & ENUM) != 0;
boolean isInterface = (tree.mods.flags & INTERFACE ) != 0; boolean isInterface = (tree.mods.flags & INTERFACE ) != 0;
boolean isRecord = (tree.mods.flags & RECORD ) != 0;
int classBegin = dis.getStartPosition(tree); int classBegin = dis.getStartPosition(tree);
int classEnd = dis.getEndPosition(tree); int classEnd = dis.getEndPosition(tree);
//debugWrap("visitClassDef: %d-%d = %s\n", classBegin, classEnd, source.substring(classBegin, classEnd)); //debugWrap("visitClassDef: %d-%d = %s\n", classBegin, classEnd, source.substring(classBegin, classEnd));
@ -151,8 +156,12 @@ class Corraller extends Visitor {
// non-enum // non-enum
boolean constructorSeen = false; boolean constructorSeen = false;
for (List<? extends JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { for (List<? extends JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
wrappedDefs.append("\n ");
JCTree t = l.head; JCTree t = l.head;
if (isRecord && t.hasTag(Tag.VARDEF) && (TreeInfo.flags(t) & RECORD) != 0) {
//record parameters are part of the record's header
continue;
}
wrappedDefs.append("\n ");
switch (t.getKind()) { switch (t.getKind()) {
case METHOD: case METHOD:
constructorSeen = constructorSeen || ((MethodTree)t).getName() == tree.name.table.names.init; constructorSeen = constructorSeen || ((MethodTree)t).getName() == tree.name.table.names.init;
@ -166,7 +175,14 @@ class Corraller extends Visitor {
} }
wrappedDefs.append(corral(t)); wrappedDefs.append(corral(t));
} }
if (!constructorSeen && !isInterface && !isEnum) { if (!constructorSeen && isRecord) {
// Generate a default constructor, since
// this is a regular record and there are no constructors
if (wrappedDefs.length() > 0) {
wrappedDefs.append("\n ");
}
wrappedDefs.append(" public " + tree.name.toString() + " " + resolutionExceptionBlock);
} else if (!constructorSeen && !isInterface && !isEnum) {
// Generate a default constructor, since // Generate a default constructor, since
// this is a regular class and there are no constructors // this is a regular class and there are no constructors
if (wrappedDefs.length() > 0) { if (wrappedDefs.length() > 0) {
@ -175,7 +191,9 @@ class Corraller extends Visitor {
wrappedDefs.append(defaultConstructor(tree)); wrappedDefs.append(defaultConstructor(tree));
} }
} }
bodyBegin = dis.getStartPosition(tree.defs.head); if (!isRecord) {
bodyBegin = dis.getStartPosition(tree.defs.head);
}
} }
Object defs = wrappedDefs.length() == 1 Object defs = wrappedDefs.length() == 1
? wrappedDefs.first() ? wrappedDefs.first()

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2020, 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 8229855
* @summary Test jump table with key value that gets out of bounds after loop unrolling.
* @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
* -Xbatch -XX:-TieredCompilation -XX:-UseSwitchProfiling
* compiler.c2.TestJumpTable
*/
package compiler.c2;
public class TestJumpTable {
public static int test() {
int res = 0;
for (int i = 10; i < 50; ++i) {
switch (i * 5) {
case 15:
case 25:
case 40:
case 101:
return 42;
case 45:
case 51:
case 60:
res++;
break;
}
}
return res;
}
public static void main(String[] args) {
for (int i = 0; i < 20_000; ++i) {
test();
}
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved. * Copyright (c) 2017, 2020, Red Hat, Inc. All rights reserved.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License version 2 only, as
@ -40,6 +40,15 @@
* @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx128m -XX:ShenandoahGCHeuristics=aggressive -XX:-UseCompressedOops TestHeapDump * @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx128m -XX:ShenandoahGCHeuristics=aggressive -XX:-UseCompressedOops TestHeapDump
*/ */
/**
* @test TestHeapDump
* @summary Tests JVMTI heap dumps
* @key gc
* @requires vm.gc.Shenandoah & !vm.graal.enabled
* @compile TestHeapDump.java
* @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx128m -XX:ShenandoahGCHeuristics=aggressive -XX:+UseStringDeduplication TestHeapDump
*/
import java.lang.ref.Reference; import java.lang.ref.Reference;
public class TestHeapDump { public class TestHeapDump {

View file

@ -67,7 +67,8 @@ void JNICALL VMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
jvmti->RunAgentThread(agent_thread, GenerateEventsThread, NULL, JVMTI_THREAD_NORM_PRIORITY); jvmti->RunAgentThread(agent_thread, GenerateEventsThread, NULL, JVMTI_THREAD_NORM_PRIORITY);
} }
jint Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { JNIEXPORT
jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti; jvmtiEnv* jvmti;
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,7 @@ import java.lang.invoke.VarHandle;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.testng.SkipException;
import org.testng.annotations.*; import org.testng.annotations.*;
import static org.testng.Assert.*; import static org.testng.Assert.*;
@ -76,8 +77,8 @@ public class TestArrays {
static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement()); static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement());
static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement()); static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement());
static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement()); static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement());
static VarHandle longHandle = doubles.varHandle(long.class, PathElement.sequenceElement()); static VarHandle longHandle = longs.varHandle(long.class, PathElement.sequenceElement());
static VarHandle doubleHandle = longs.varHandle(double.class, PathElement.sequenceElement()); static VarHandle doubleHandle = doubles.varHandle(double.class, PathElement.sequenceElement());
static void initBytes(MemoryAddress base, SequenceLayout seq, BiConsumer<MemoryAddress, Long> handleSetter) { static void initBytes(MemoryAddress base, SequenceLayout seq, BiConsumer<MemoryAddress, Long> handleSetter) {
for (long i = 0; i < seq.elementCount().getAsLong() ; i++) { for (long i = 0; i < seq.elementCount().getAsLong() ; i++) {
@ -103,8 +104,13 @@ public class TestArrays {
} }
} }
@Test(expectedExceptions = UnsupportedOperationException.class) @Test(expectedExceptions = { UnsupportedOperationException.class,
OutOfMemoryError.class })
public void testTooBigForArray() { public void testTooBigForArray() {
if (System.getProperty("sun.arch.data.model").equals("32")) {
throw new SkipException("32-bit Unsafe does not support this allocation size");
}
MemorySegment.allocateNative((long) Integer.MAX_VALUE * 2).toByteArray(); MemorySegment.allocateNative((long) Integer.MAX_VALUE * 2).toByteArray();
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,6 +70,7 @@ import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import jdk.internal.foreign.MemoryAddressImpl; import jdk.internal.foreign.MemoryAddressImpl;
import org.testng.SkipException;
import org.testng.annotations.*; import org.testng.annotations.*;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
@ -119,8 +120,8 @@ public class TestByteBuffer {
static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement()); static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement());
static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement()); static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement());
static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement()); static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement());
static VarHandle longHandle = doubles.varHandle(long.class, PathElement.sequenceElement()); static VarHandle longHandle = longs.varHandle(long.class, PathElement.sequenceElement());
static VarHandle doubleHandle = longs.varHandle(double.class, PathElement.sequenceElement()); static VarHandle doubleHandle = doubles.varHandle(double.class, PathElement.sequenceElement());
static void initTuples(MemoryAddress base) { static void initTuples(MemoryAddress base) {
@ -247,6 +248,13 @@ public class TestByteBuffer {
} }
} }
static void checkByteArrayAlignment(MemoryLayout layout) {
if (layout.bitSize() > 32
&& System.getProperty("sun.arch.data.model").equals("32")) {
throw new SkipException("avoid unaligned access on 32-bit system");
}
}
@Test(dataProvider = "bufferOps") @Test(dataProvider = "bufferOps")
public void testScopedBuffer(Function<ByteBuffer, Buffer> bufferFactory, Map<Method, Object[]> members) { public void testScopedBuffer(Function<ByteBuffer, Buffer> bufferFactory, Map<Method, Object[]> members) {
Buffer bb; Buffer bb;
@ -338,6 +346,7 @@ public class TestByteBuffer {
@Test(dataProvider="resizeOps") @Test(dataProvider="resizeOps")
public void testResizeHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) { public void testResizeHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) {
checkByteArrayAlignment(seq.elementLayout());
int capacity = (int)seq.byteSize(); int capacity = (int)seq.byteSize();
MemoryAddress base = MemorySegment.ofArray(new byte[capacity]).baseAddress(); MemoryAddress base = MemorySegment.ofArray(new byte[capacity]).baseAddress();
initializer.accept(base); initializer.accept(base);
@ -346,6 +355,7 @@ public class TestByteBuffer {
@Test(dataProvider="resizeOps") @Test(dataProvider="resizeOps")
public void testResizeBuffer(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) { public void testResizeBuffer(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) {
checkByteArrayAlignment(seq.elementLayout());
int capacity = (int)seq.byteSize(); int capacity = (int)seq.byteSize();
MemoryAddress base = MemorySegment.ofByteBuffer(ByteBuffer.wrap(new byte[capacity])).baseAddress(); MemoryAddress base = MemorySegment.ofByteBuffer(ByteBuffer.wrap(new byte[capacity])).baseAddress();
initializer.accept(base); initializer.accept(base);
@ -354,6 +364,7 @@ public class TestByteBuffer {
@Test(dataProvider="resizeOps") @Test(dataProvider="resizeOps")
public void testResizeRoundtripHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) { public void testResizeRoundtripHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) {
checkByteArrayAlignment(seq.elementLayout());
int capacity = (int)seq.byteSize(); int capacity = (int)seq.byteSize();
byte[] arr = new byte[capacity]; byte[] arr = new byte[capacity];
MemorySegment segment = MemorySegment.ofArray(arr); MemorySegment segment = MemorySegment.ofArray(arr);
@ -382,13 +393,19 @@ public class TestByteBuffer {
leaked.asByteBuffer(); leaked.asByteBuffer();
} }
@Test(expectedExceptions = UnsupportedOperationException.class) @Test(expectedExceptions = { UnsupportedOperationException.class,
OutOfMemoryError.class })
public void testTooBigForByteBuffer() { public void testTooBigForByteBuffer() {
if (System.getProperty("sun.arch.data.model").equals("32")) {
throw new SkipException("32-bit Unsafe does not support this allocation size");
}
MemorySegment.allocateNative((long) Integer.MAX_VALUE * 2).asByteBuffer(); MemorySegment.allocateNative((long) Integer.MAX_VALUE * 2).asByteBuffer();
} }
@Test(dataProvider="resizeOps") @Test(dataProvider="resizeOps")
public void testCopyHeapToNative(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) { public void testCopyHeapToNative(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) {
checkByteArrayAlignment(seq.elementLayout());
int bytes = (int)seq.byteSize(); int bytes = (int)seq.byteSize();
try (MemorySegment nativeArray = MemorySegment.allocateNative(bytes); try (MemorySegment nativeArray = MemorySegment.allocateNative(bytes);
MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) { MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) {
@ -400,6 +417,7 @@ public class TestByteBuffer {
@Test(dataProvider="resizeOps") @Test(dataProvider="resizeOps")
public void testCopyNativeToHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) { public void testCopyNativeToHeap(Consumer<MemoryAddress> checker, Consumer<MemoryAddress> initializer, SequenceLayout seq) {
checkByteArrayAlignment(seq.elementLayout());
int bytes = (int)seq.byteSize(); int bytes = (int)seq.byteSize();
try (MemorySegment nativeArray = MemorySegment.allocateNative(seq); try (MemorySegment nativeArray = MemorySegment.allocateNative(seq);
MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) { MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes])) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/* /*
* @test * @test
* @requires vm.bits != "32"
* @run testng TestMemoryAlignment * @run testng TestMemoryAlignment
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -58,7 +58,8 @@ public class TestSegments {
MemorySegment.allocateNative(layout); MemorySegment.allocateNative(layout);
} }
@Test(expectedExceptions = OutOfMemoryError.class) @Test(expectedExceptions = { OutOfMemoryError.class,
IllegalArgumentException.class })
public void testAllocateTooBig() { public void testAllocateTooBig() {
MemorySegment.allocateNative(Long.MAX_VALUE); MemorySegment.allocateNative(Long.MAX_VALUE);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -16,7 +16,7 @@
* 2 along with this work; if not, write to the Free Software Foundation, * 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 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 * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
* *
@ -24,88 +24,89 @@
#include "jni.h" #include "jni.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
JNIEXPORT jbyte JNICALL JNIEXPORT jbyte JNICALL
Java_TestNative_getByteRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getByteRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jbyte *arr = (jbyte*)addr; jbyte *arr = (jbyte*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jbyte JNICALL JNIEXPORT jbyte JNICALL
Java_TestNative_getByteBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getByteBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getByteRaw(env, cls, addr, index); return Java_TestNative_getByteRaw(env, cls, addr, index);
} }
JNIEXPORT jchar JNICALL JNIEXPORT jchar JNICALL
Java_TestNative_getCharRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getCharRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jchar *arr = (jchar*)addr; jchar *arr = (jchar*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jchar JNICALL JNIEXPORT jchar JNICALL
Java_TestNative_getCharBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getCharBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getCharRaw(env, cls, addr, index); return Java_TestNative_getCharRaw(env, cls, addr, index);
} }
JNIEXPORT jshort JNICALL JNIEXPORT jshort JNICALL
Java_TestNative_getShortRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getShortRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jshort *arr = (jshort*)addr; jshort *arr = (jshort*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jshort JNICALL JNIEXPORT jshort JNICALL
Java_TestNative_getShortBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getShortBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getShortRaw(env, cls, addr, index); return Java_TestNative_getShortRaw(env, cls, addr, index);
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_TestNative_getIntRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getIntRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jint *arr = (jint*)addr; jint *arr = (jint*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_TestNative_getIntBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getIntBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getIntRaw(env, cls, addr, index); return Java_TestNative_getIntRaw(env, cls, addr, index);
} }
JNIEXPORT jfloat JNICALL JNIEXPORT jfloat JNICALL
Java_TestNative_getFloatRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getFloatRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jfloat *arr = (jfloat*)addr; jfloat *arr = (jfloat*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jfloat JNICALL JNIEXPORT jfloat JNICALL
Java_TestNative_getFloatBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getFloatBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getFloatRaw(env, cls, addr, index); return Java_TestNative_getFloatRaw(env, cls, addr, index);
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_TestNative_getLongRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getLongRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jlong *arr = (jlong*)addr; jlong *arr = (jlong*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_TestNative_getLongBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getLongBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getLongRaw(env, cls, addr, index); return Java_TestNative_getLongRaw(env, cls, addr, index);
} }
JNIEXPORT jdouble JNICALL JNIEXPORT jdouble JNICALL
Java_TestNative_getDoubleRaw(JNIEnv *env, jclass cls, jlong addr, jint index) { Java_TestNative_getDoubleRaw(JNIEnv *env, jclass cls, jlong addr, jint index) {
jdouble *arr = (jdouble*)addr; jdouble *arr = (jdouble*)(uintptr_t)addr;
return arr[index]; return arr[index];
} }
JNIEXPORT jdouble JNICALL JNIEXPORT jdouble JNICALL
Java_TestNative_getDoubleBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) { Java_TestNative_getDoubleBuffer(JNIEnv *env, jclass cls, jobject buf, jint index) {
jlong addr = (jlong)(*env)->GetDirectBufferAddress(env, buf); jlong addr = (jlong)(uintptr_t)(*env)->GetDirectBufferAddress(env, buf);
return Java_TestNative_getDoubleRaw(env, cls, addr, index); return Java_TestNative_getDoubleRaw(env, cls, addr, index);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -41,7 +41,7 @@ import tests.Result;
/* /*
* @test * @test
* @bug 8152143 8152704 8155649 8165804 8185841 8176841 8190918 * @bug 8152143 8152704 8155649 8165804 8185841 8176841 8190918
* 8179071 8202537 8221432 * 8179071 8202537 8221432 8222098
* @summary IncludeLocalesPlugin tests * @summary IncludeLocalesPlugin tests
* @author Naoto Sato * @author Naoto Sato
* @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g) * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
@ -56,7 +56,7 @@ import tests.Result;
* jdk.compiler * jdk.compiler
* @build tests.* * @build tests.*
* @build tools.jlink.plugins.GetAvailableLocales * @build tools.jlink.plugins.GetAvailableLocales
* @run main/othervm -Xmx1g IncludeLocalesPluginTest * @run main/othervm/timeout=180 -Xmx1g IncludeLocalesPluginTest
*/ */
public class IncludeLocalesPluginTest { public class IncludeLocalesPluginTest {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8235474 * @bug 8235474 8236715
* @summary Tests for evalution of records * @summary Tests for evalution of records
* @modules jdk.jshell * @modules jdk.jshell
* @build KullaTesting TestingInputStream ExpectedDiagnostic * @build KullaTesting TestingInputStream ExpectedDiagnostic
@ -33,6 +33,8 @@
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
import jdk.jshell.Snippet.Status;
import jdk.jshell.UnresolvedReferenceException;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
@ -46,6 +48,24 @@ public class RecordsTest extends KullaTesting {
assertEval("r.i()", "42"); assertEval("r.i()", "42");
} }
public void testRecordCorralling() {
//simple record with a mistake that can be fixed by corralling:
assertEval("record R1(int i) { int g() { return j; } }", ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_DEFINED, true, null));
assertEval("R1 r1 = new R1(1);", null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(Status.VALID));
//record with a concise constructor and a mistake take can be fixed by corralling:
assertEval("record R2(int i) { public R2 {} int g() { return j; } }", ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_DEFINED, true, null));
assertEval("R2 r2 = new R2(1);", null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(Status.VALID));
//record with a full constructor and a mistake take can be fixed by corralling:
assertEval("record R3(int i) { public R3(int i) {this.i = i;} int g() { return j; } }", ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_DEFINED, true, null));
assertEval("R3 r3 = new R3(1);", null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(Status.VALID));
//record with an accessor and a mistake take can be fixed by corralling:
assertEval("record R4(int i) { public int i() { return i; } int g() { return j; } }", ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_DEFINED, true, null));
assertEval("R4 r4 = new R4(1);", null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(Status.VALID));
//record with an accessor with a mistake take can be fixed by corralling:
assertEval("record R5(int i) { public int i() { return j; } }", ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_DEFINED, true, null));
assertEval("R5 r5 = new R5(1);", null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, added(Status.VALID));
}
public void testRecordField() { public void testRecordField() {
assertEquals(varKey(assertEval("String record = \"\";")).name(), "record"); assertEquals(varKey(assertEval("String record = \"\";")).name(), "record");
assertEval("record.length()", "0"); assertEval("record.length()", "0");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -100,4 +100,8 @@ public class ToolLocalSimpleTest extends ToolSimpleTest {
// can't set --enable-preview for local, ignore // can't set --enable-preview for local, ignore
} }
@Override
public void testRecords() {
// can't set --enable-preview for local, ignore
}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715
* @summary Simple jshell tool tests * @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.main
@ -902,4 +902,14 @@ public class ToolSimpleTest extends ReplToolTesting {
a -> assertCommandOutputContains(a, "a", "A@") a -> assertCommandOutputContains(a, "a", "A@")
); );
} }
@Test
public void testRecords() {
test(new String[] {"--enable-preview"},
(a) -> assertCommandOutputContains(a, "record R(int i) { public int g() { return j; } }",
"| created record R, however, it cannot be instantiated or its methods invoked until variable j is declared"),
(a) -> assertCommandOutputContains(a, "new R(0)",
"| attempted to use record R which cannot be instantiated or its methods invoked until variable j is declared")
);
}
} }

View file

@ -437,6 +437,17 @@ public class RecordCompilationTests extends CompilationTestCase {
assertOK("record R(int x) { public R { Runnable r = () -> { return; };} }"); assertOK("record R(int x) { public R { Runnable r = () -> { return; };} }");
} }
public void testArgumentsAreNotFinalInCompact() {
assertOK(
"""
record R(int x) {
public R {
x++;
}
}
""");
}
public void testNoNativeMethods() { public void testNoNativeMethods() {
assertFail("compiler.err.mod.not.allowed.here", "record R(int x) { # }", assertFail("compiler.err.mod.not.allowed.here", "record R(int x) { # }",
"public native R {}"); "public native R {}");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8214031 8214114 * @bug 8214031 8214114 8236546
* @summary Verify switch expressions embedded in various statements work properly. * @summary Verify switch expressions embedded in various statements work properly.
* @compile ExpressionSwitchEmbedding.java * @compile ExpressionSwitchEmbedding.java
* @run main ExpressionSwitchEmbedding * @run main ExpressionSwitchEmbedding
@ -321,6 +321,13 @@ public class ExpressionSwitchEmbedding {
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
{
String s = "";
Object o = switch (s) { default -> s != null && s == s; };
if (!(Boolean) o) {
throw new IllegalStateException();
}
}
} }
private void throwException() { private void throwException() {

View file

@ -0,0 +1,138 @@
/*
* Copyright (c) 2020, 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
* @summary Tests jdeps option on a MR jar with missing dependences
* @library ../lib
* @build CompilerUtils JdepsUtil
* @modules jdk.jdeps/com.sun.tools.jdeps
* @run testng MissingDepsTest
*/
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.spi.ToolProvider;
import java.util.stream.Stream;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertEquals;
public class MissingDepsTest {
private static final String TEST_SRC = System.getProperty("test.src");
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
private static final Path MODS_DIR = Paths.get("mods");
private static final Path CLASSES_DIR = Paths.get("classes");
private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").orElseThrow();
private static final String VERSION = "13";
private static final Set<String> modules = Set.of("m1", "m2");
/**
* Compiles classes used by the test
*/
@BeforeTest
public void compileAll() throws Exception {
CompilerUtils.cleanDir(MODS_DIR);
modules.forEach(mn ->
assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
// compile a versioned class file
Path versionedFile = Paths.get(TEST_SRC, "p/internal/X.java");
assertTrue(CompilerUtils.compile(versionedFile, CLASSES_DIR, "-cp", MODS_DIR.resolve("m2").toString()));
// create a modular multi-release m1.jar
JAR_TOOL.run(System.out, System.err, "cf", "m1.jar",
"-C", MODS_DIR.resolve("m1").toString(), ".");
JAR_TOOL.run(System.out, System.err, "uf", "m1.jar",
"--release", VERSION, "-C", CLASSES_DIR.toString(), "p/internal/X.class");
// create a non-modular multi-release mr.jar
JAR_TOOL.run(System.out, System.err, "cf", "mr.jar",
"-C", MODS_DIR.resolve("m1").toString(), "p/Foo.class",
"--release", VERSION, "-C", CLASSES_DIR.toString(), "p/internal/X.class");
}
@Test
public void checkModuleDeps() {
JdepsTest test = new JdepsTest();
test.options(List.of("--module-path", "m1.jar", "--multi-release", VERSION, "--check", "m1"));
test.checkMissingDeps();
test.ignoreMissingDeps("requires java.management");
}
@Test
public void genModuleInfo() {
JdepsTest test = new JdepsTest();
test.options(List.of("--generate-module-info", ".", "--multi-release", VERSION, "mr.jar"));
test.checkMissingDeps();
Path file = Paths.get("mr", "versions", VERSION, "module-info.java");
test.ignoreMissingDeps(file.toString());
assertTrue(Files.exists(file));
}
@Test
public void listModuleDeps() {
JdepsTest test = new JdepsTest();
test.options(List.of("--list-deps", "--multi-release", VERSION, "mr.jar"));
test.checkMissingDeps();
test.ignoreMissingDeps("java.management");
}
class JdepsTest {
// set DEBUG to true to show the jdeps output
static final boolean DEBUG = false;
List<String> options;
JdepsTest options(List<String> options) {
this.options = options;
return this;
}
private void checkMissingDeps() {
JdepsRunner jdepsRunner = new JdepsRunner(options.toArray(new String[0]));
int rc = jdepsRunner.run(DEBUG);
assertTrue(rc != 0);
String regex = "\\s+13/p.internal.X\\s+->\\s+q.T\\s+not found";
assertTrue(Arrays.stream(jdepsRunner.output()).anyMatch(l -> l.matches(regex)));
}
public void ignoreMissingDeps(String expected) {
JdepsRunner jdepsRunner = new JdepsRunner(Stream.concat(Stream.of("--ignore-missing-deps"), options.stream())
.toArray(String[]::new));
int rc = jdepsRunner.run(DEBUG);
assertTrue(rc == 0);
System.out.println("Expected: " + expected);
assertTrue(Arrays.stream(jdepsRunner.output()).anyMatch(l -> l.contains(expected)));
}
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2020, 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 p.internal;
import java.lang.management.*;
class X implements q.T {
public void upTime() {
ManagementFactory.getRuntimeMXBean().getUptime();
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, 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.
*/
module m1 {
requires static m2;
exports p;
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020, 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 p;
public class Foo implements Runnable {
public void run() {
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2020, 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.
*/
module m2 {
exports q;
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020, 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 q;
public interface Bar {
default String name() {
return "";
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, 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 q;
public interface T {
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -86,7 +86,7 @@ public class CheckModuleTest {
jdeps.appModulePath(MODS_DIR.toString()); jdeps.appModulePath(MODS_DIR.toString());
ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name)); ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name));
assertTrue(analyzer.run()); assertTrue(analyzer.run(false));
jdeps.dumpOutput(System.err); jdeps.dumpOutput(System.err);
ModuleDescriptor[] descriptors = analyzer.descriptors(name); ModuleDescriptor[] descriptors = analyzer.descriptors(name);
@ -146,7 +146,7 @@ public class CheckModuleTest {
jdeps.appModulePath(MODS_DIR.toString()); jdeps.appModulePath(MODS_DIR.toString());
ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name)); ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name));
assertTrue(analyzer.run()); assertTrue(analyzer.run(false));
jdeps.dumpOutput(System.err); jdeps.dumpOutput(System.err);
// compare the module descriptors and the suggested versions // compare the module descriptors and the suggested versions