This commit is contained in:
Jesper Wilhelmsson 2017-02-04 03:29:40 +01:00
commit 3560e1733c
307 changed files with 5416 additions and 2540 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2016, 2017, 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
@ -121,7 +121,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
-buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \
-buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \
-makeBinary $(call FixPath, $(MAKE)) \
-makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \
-makeOutput $(call FixPath, $(JDK_OUTPUTDIR)/bin/server) \
-absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
-absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
$(EXTRACTED_DEFINES_client) \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2017, 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
@ -114,8 +114,8 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
tag(cfg, "CodeAnalysisRuleAssemblies");
}
for (BuildConfig cfg : allConfigs) {
tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile import-hotspot LOG=info");
tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot import-hotspot LOG=info");
tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile hotspot LOG=info");
tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot hotspot LOG=info");
tagData(cfg, "NMakeCleanCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot LOG=info");
tagData(cfg, "NMakeOutput", cfg.get("MakeOutput") + Util.sep + "jvm.dll");
tagData(cfg, "NMakePreprocessorDefinitions", Util.join(";", cfg.getDefines()));

View File

@ -192,4 +192,3 @@ JVM_AddModulePackage
JVM_AddReadsModule
JVM_DefineModule
JVM_SetBootLoaderUnnamedModule
JVM_GetModuleByPackageName

File diff suppressed because it is too large Load Diff

View File

@ -532,8 +532,14 @@ void LIR_Assembler::poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo*
void LIR_Assembler::return_op(LIR_Opr result) {
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");
// Pop the stack before the safepoint code
__ remove_frame(initial_frame_size_in_bytes());
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
__ reserved_stack_check();
}
address polling_page(os::get_polling_page());
__ read_polling_page(rscratch1, polling_page, relocInfo::poll_return_type);
__ ret(lr);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -1179,6 +1179,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
// Is marking still active?
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
__ ldrw(tmp, in_progress);
} else {
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ ldrb(tmp, in_progress);
}
__ cbzw(tmp, done);
// Can we store original value in the thread's buffer?
__ ldr(tmp, queue_index);
__ cbz(tmp, runtime);

View File

@ -375,7 +375,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif
@ -629,6 +630,7 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);

View File

@ -46,6 +46,9 @@
// [pointer to locals ] = locals() locals_offset
// [constant pool cache ] = cache() cache_offset
// [klass of method ] = mirror() mirror_offset
// [padding ]
// [methodData ] = mdp() mdx_offset
// [methodOop ] = method() method_offset

View File

@ -82,7 +82,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;

View File

@ -53,4 +53,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
// evidence that it's worth doing.
#define DEOPTIMIZE_WHEN_PATCHING
#define SUPPORT_RESERVED_STACK_AREA
#endif // CPU_AARCH64_VM_GLOBALDEFINITIONS_AARCH64_HPP

View File

@ -50,7 +50,7 @@ define_pd_global(intx, InlineFrequencyCount, 100);
// stack if compiled for unix and LP64. To pass stack overflow tests we need
// 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5))
#define DEFAULT_STACK_RESERVED_PAGES (0)
#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES

View File

@ -619,6 +619,22 @@ void InterpreterMacroAssembler::remove_activation(
// get sender esp
ldr(esp,
Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize));
if (StackReservedPages > 0) {
// testing if reserved zone needs to be re-enabled
Label no_reserved_zone_enabling;
ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
cmp(esp, rscratch1);
br(Assembler::LS, no_reserved_zone_enabling);
call_VM_leaf(
CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_delayed_StackOverflowError));
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
// remove frame anchor
leave();
// If we're returning to interpreted code we will shortly be

View File

@ -402,6 +402,30 @@ void MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) {
}
}
void MacroAssembler::reserved_stack_check() {
// testing if reserved zone needs to be enabled
Label no_reserved_zone_enabling;
ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
cmp(sp, rscratch1);
br(Assembler::LO, no_reserved_zone_enabling);
enter(); // LR and FP are live.
lea(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone));
mov(c_rarg0, rthread);
blr(rscratch1);
leave();
// We have already removed our own frame.
// throw_delayed_StackOverflowError will think that it's been
// called by our caller.
lea(rscratch1, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
br(rscratch1);
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
int MacroAssembler::biased_locking_enter(Register lock_reg,
Register obj_reg,
Register swap_reg,

View File

@ -957,6 +957,9 @@ public:
// stack overflow + shadow pages. Also, clobbers tmp
void bang_stack_size(Register size, Register tmp);
// Check for reserved stack access in method being exited (for JIT)
void reserved_stack_check();
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp,
int offset);

View File

@ -4676,8 +4676,11 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
SharedRuntime::
throw_StackOverflowError));
SharedRuntime::throw_StackOverflowError));
StubRoutines::_throw_delayed_StackOverflowError_entry =
generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
SharedRuntime::throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it
StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2017, 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
@ -551,6 +551,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
const Register r_index_1 = R1;
const Register r_buffer_2 = R2;
Address queue_active(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active()));
Address queue_index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
@ -559,6 +561,11 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
// Is marking still active?
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ ldrb(R1, queue_active);
__ cbz(R1, done);
__ ldr(r_index_1, queue_index);
__ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
__ ldr(r_buffer_2, buffer);

View File

@ -364,7 +364,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
}
#endif

View File

@ -75,7 +75,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
assert(_cb->as_compiled_method()->insts_contains(_pc), "original PC must be in CompiledMethod");
assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -741,7 +741,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp = R14;
Register tmp2 = R15;
Label refill, restart;
Label refill, restart, marking_not_active;
int satb_q_active_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@ -753,6 +756,16 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ std(tmp, -16, R1_SP);
__ std(tmp2, -24, R1_SP);
// Is marking still active?
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
__ lwz(tmp, satb_q_active_byte_offset, R16_thread);
} else {
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ lbz(tmp, satb_q_active_byte_offset, R16_thread);
}
__ cmpdi(CCR0, tmp, 0);
__ beq(CCR0, marking_not_active);
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@ -769,6 +782,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ std(tmp, satb_q_index_byte_offset, R16_thread);
__ stdx(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card>
__ bind(marking_not_active);
// Restore temp registers and return-from-leaf.
__ ld(tmp2, -24, R1_SP);
__ ld(tmp, -16, R1_SP);

View File

@ -2569,7 +2569,7 @@ void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register
}
// Spin and retry if lock is busy.
// inputs: box_Reg (monitor address)
// inputs: owner_addr_Reg (monitor address)
// : retry_count_Reg
// output: retry_count_Reg decremented by 1
// CTR is killed
@ -2577,15 +2577,22 @@ void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register o
Label SpinLoop, doneRetry;
addic_(retry_count_Reg, retry_count_Reg, -1);
blt(CCR0, doneRetry);
li(R0, RTMSpinLoopCount);
mtctr(R0);
if (RTMSpinLoopCount > 1) {
li(R0, RTMSpinLoopCount);
mtctr(R0);
}
bind(SpinLoop);
smt_yield(); // Can't use waitrsv(). No permission (SIGILL).
bdz(retryLabel);
ld(R0, 0, owner_addr_Reg);
cmpdi(CCR0, R0, 0);
bne(CCR0, SpinLoop);
if (RTMSpinLoopCount > 1) {
bdz(retryLabel);
ld(R0, 0, owner_addr_Reg);
cmpdi(CCR0, R0, 0);
bne(CCR0, SpinLoop);
}
b(retryLabel);
bind(doneRetry);

View File

@ -327,7 +327,10 @@ void VM_Version::initialize() {
warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
FLAG_SET_DEFAULT(RTMAbortRatio, 50);
}
guarantee(RTMSpinLoopCount > 0, "unsupported");
if (RTMSpinLoopCount < 0) {
warning("RTMSpinLoopCount must not be a negative value, resetting it to 0");
FLAG_SET_DEFAULT(RTMSpinLoopCount, 0);
}
#else
// Only C2 does RTM locking optimization.
// Can't continue because UseRTMLocking affects UseBiasedLocking flag

View File

@ -1105,16 +1105,16 @@ void LIR_Assembler::reg2mem(LIR_Opr from, LIR_Opr dest_opr, BasicType type,
}
case T_FLOAT :
if (short_disp) {
__ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
__ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
} else {
__ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
__ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
}
break;
case T_DOUBLE:
if (short_disp) {
__ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
__ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
} else {
__ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
__ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
}
break;
default: ShouldNotReachHere();
@ -1148,6 +1148,10 @@ void LIR_Assembler::return_op(LIR_Opr result) {
__ restore_return_pc();
}
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
__ reserved_stack_check(Z_R14);
}
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -784,7 +784,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp = Z_R6; // Must be non-volatile because it is used to save pre_val.
Register tmp2 = Z_R7;
Label refill, restart;
Label refill, restart, marking_not_active;
int satb_q_active_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@ -796,6 +799,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ z_stg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
// Is marking still active?
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
__ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
} else {
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
}
__ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@ -810,6 +822,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] := <address_of_card>
__ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
__ bind(marking_not_active);
// Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
__ z_lg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);

View File

@ -52,4 +52,6 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
// The expected size in bytes of a cache line, used to pad data structures.
#define DEFAULT_CACHE_LINE_SIZE 256
#define SUPPORT_RESERVED_STACK_AREA
#endif // CPU_S390_VM_GLOBALDEFINITIONS_S390_HPP

View File

@ -56,7 +56,7 @@ define_pd_global(intx, InlineSmallCode, 2000);
// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
// stack. To pass stack overflow tests we need 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
#define DEFAULT_STACK_RESERVED_PAGES (0)
#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES

View File

@ -860,16 +860,39 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
bool throw_monitor_exception,
bool install_monitor_exception,
bool notify_jvmti) {
BLOCK_COMMENT("remove_activation {");
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
// Save result (push state before jvmti call and pop it afterwards) and notify jvmti.
notify_method_exit(false, state, notify_jvmti ? NotifyJVMTI : SkipNotifyJVMTI);
if (StackReservedPages > 0) {
BLOCK_COMMENT("reserved_stack_check:");
// Test if reserved zone needs to be enabled.
Label no_reserved_zone_enabling;
// Compare frame pointers. There is no good stack pointer, as with stack
// frame compression we can get different SPs when we do calls. A subsequent
// call could have a smaller SP, so that this compare succeeds for an
// inner call of the method annotated with ReservedStack.
z_lg(Z_R0, Address(Z_SP, (intptr_t)_z_abi(callers_sp)));
z_clg(Z_R0, Address(Z_thread, JavaThread::reserved_stack_activation_offset())); // Compare with frame pointer in memory.
z_brl(no_reserved_zone_enabling);
// Enable reserved zone again, throw stack overflow exception.
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError));
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
verify_oop(Z_tos, state);
verify_thread();
pop_interpreter_frame(return_pc, Z_ARG2, Z_ARG3);
BLOCK_COMMENT("} remove_activation");
}
// lock object

View File

@ -2666,6 +2666,32 @@ void MacroAssembler::bang_stack_with_offset(int offset) {
}
}
void MacroAssembler::reserved_stack_check(Register return_pc) {
// Test if reserved zone needs to be enabled.
Label no_reserved_zone_enabling;
assert(return_pc == Z_R14, "Return pc must be in R14 before z_br() to StackOverflow stub.");
BLOCK_COMMENT("reserved_stack_check {");
z_clg(Z_SP, Address(Z_thread, JavaThread::reserved_stack_activation_offset()));
z_brl(no_reserved_zone_enabling);
// Enable reserved zone again, throw stack overflow exception.
save_return_pc();
push_frame_abi160(0);
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
pop_frame();
restore_return_pc();
load_const_optimized(Z_R1, StubRoutines::throw_delayed_StackOverflowError_entry());
// Don't use call() or z_basr(), they will invalidate Z_R14 which contains the return pc.
z_br(Z_R1);
should_not_reach_here();
bind(no_reserved_zone_enabling);
BLOCK_COMMENT("} reserved_stack_check");
}
// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
void MacroAssembler::tlab_allocate(Register obj,
Register var_size_in_bytes,

View File

@ -627,6 +627,11 @@ class MacroAssembler: public Assembler {
// Stack overflow checking
void bang_stack_with_offset(int offset);
// Check for reserved stack access in method being exited. If the reserved
// stack area was accessed, protect it again and throw StackOverflowError.
// Uses Z_R1.
void reserved_stack_check(Register return_pc);
// Atomics
// -- none?

View File

@ -909,15 +909,8 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// If this does safepoint polling, then do it here.
bool need_polling = do_polling() && C->is_method_compilation();
// Touch the polling page.
// Part 1: get the page's address.
if (need_polling) {
AddressLiteral pp(os::get_polling_page());
__ load_const_optimized(Z_R1_scratch, pp);
}
// Pop frame, restore return_pc, and all stuff needed by interpreter.
// Pop frame by add insted of load (a penny saved is a penny got :-).
// Pop frame by add instead of load (a penny saved is a penny got :-).
int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
int retPC_offset = frame_size_in_bytes + _z_abi16(return_pc);
if (Displacement::is_validDisp(retPC_offset)) {
@ -928,9 +921,14 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ restore_return_pc();
}
// Touch the polling page,
// part 2: touch the page now.
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
__ reserved_stack_check(Z_R14);
}
// Touch the polling page.
if (need_polling) {
AddressLiteral pp(os::get_polling_page());
__ load_const_optimized(Z_R1_scratch, pp);
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
@ -939,7 +937,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
}
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
// variable size. determine dynamically.
// Variable size. determine dynamically.
return MachNode::size(ra_);
}

View File

@ -2433,13 +2433,12 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
StubRoutines::_throw_delayed_StackOverflowError_entry =
generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError), false);
//----------------------------------------------------------------------
// Entry points that are platform specific.
// Build this early so it's available for the interpreter.
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
if (UseCRC32Intrinsics) {
// We have no CRC32 table on z/Architecture.

View File

@ -1112,16 +1112,21 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// top_frame_size = TOP_IJAVA_FRAME_ABI + max_stack + size of interpreter state
__ add2reg(top_frame_size,
frame::z_top_ijava_frame_abi_size +
frame::z_ijava_state_size +
frame::interpreter_frame_monitor_size() * wordSize,
frame::z_ijava_state_size +
frame::interpreter_frame_monitor_size() * wordSize,
max_stack);
// Check if there's room for the new frame...
Register frame_size = max_stack; // Reuse the regiser for max_stack.
__ z_lgr(frame_size, Z_SP);
__ z_sgr(frame_size, sp_after_resize);
__ z_agr(frame_size, top_frame_size);
generate_stack_overflow_check(frame_size, fp/*tmp1*/);
if (!native_call) {
// Stack overflow check.
// Native calls don't need the stack size check since they have no
// expression stack and the arguments are already on the stack and
// we only add a handful of words to the stack.
Register frame_size = max_stack; // Reuse the regiser for max_stack.
__ z_lgr(frame_size, Z_SP);
__ z_sgr(frame_size, sp_after_resize);
__ z_agr(frame_size, top_frame_size);
generate_stack_overflow_check(frame_size, fp/*tmp1*/);
}
DEBUG_ONLY(__ z_cg(Z_R14, _z_abi16(return_pc), Z_SP));
__ asm_assert_eq("killed Z_R14", 0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, 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
@ -694,6 +694,7 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
int store_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
assert(base != O7, "destroying register");
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
@ -712,9 +713,12 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType
case T_LONG :
#ifdef _LP64
if (unaligned || PatchALot) {
__ srax(from_reg->as_register_lo(), 32, O7);
// Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem)
assert(G3_scratch != base, "can't handle this");
assert(G3_scratch != from_reg->as_register_lo(), "can't handle this");
__ srax(from_reg->as_register_lo(), 32, G3_scratch);
__ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes);
__ stw(O7, base, offset + hi_word_offset_in_bytes);
__ stw(G3_scratch, base, offset + hi_word_offset_in_bytes);
} else {
__ stx(from_reg->as_register_lo(), base, offset);
}
@ -821,7 +825,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
case T_SHORT : __ ldsh(base, offset, to_reg->as_register()); break;
case T_INT : __ ld(base, offset, to_reg->as_register()); break;
case T_LONG :
if (!unaligned) {
if (!unaligned && !PatchALot) {
#ifdef _LP64
__ ldx(base, offset, to_reg->as_register_lo());
#else
@ -1297,7 +1301,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
__ add(src, addr->index()->as_register(), O7);
__ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();
@ -1424,7 +1428,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
__ add(src, addr->index()->as_register(), O7);
__ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -856,7 +856,9 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp2 = G3_scratch;
Label refill, restart;
bool with_frame = false; // I don't know if we can do with-frame.
int satb_q_active_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@ -864,6 +866,17 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_buf());
// Is marking still active?
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
__ ld(G2_thread, satb_q_active_byte_offset, tmp);
} else {
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
}
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
__ retl();
__ delayed()->nop();
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -1623,6 +1623,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
NOT_LP64(__ get_thread(thread);)
Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active()));
Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
@ -1631,6 +1633,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
// Is marking still active?
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
__ cmpl(queue_active, 0);
} else {
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
__ cmpb(queue_active, 0);
}
__ jcc(Assembler::equal, done);
// Can we store original value in the thread's buffer?
__ movptr(tmp, queue_index);

View File

@ -376,7 +376,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains(original_pc), "original PC must be in CompiledMethod");
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif

View File

@ -75,7 +75,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
if (_cb->is_deoptimization_stub()) {

View File

@ -3499,12 +3499,12 @@ void MacroAssembler::movdqu(XMMRegister dst, XMMRegister src) {
}
}
void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) {
void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg) {
if (reachable(src)) {
movdqu(dst, as_Address(src));
} else {
lea(rscratch1, src);
movdqu(dst, Address(rscratch1, 0));
lea(scratchReg, src);
movdqu(dst, Address(scratchReg, 0));
}
}

View File

@ -1085,7 +1085,7 @@ public:
void movdqu(Address dst, XMMRegister src);
void movdqu(XMMRegister dst, Address src);
void movdqu(XMMRegister dst, XMMRegister src);
void movdqu(XMMRegister dst, AddressLiteral src);
void movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg = rscratch1);
// AVX Unaligned forms
void vmovdqu(Address dst, XMMRegister src);
void vmovdqu(XMMRegister dst, Address src);

View File

@ -817,7 +817,7 @@ enum {
movl(d, Address(CTX, 4*3));
movl(e, Address(CTX, 4*4));
movl(f, Address(CTX, 4*5));
movl(g, Address(CTX, 4*6));
// load g - r10 after it is used as scratch
movl(h, Address(CTX, 4*7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask;
@ -825,6 +825,8 @@ enum {
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
movl(g, Address(CTX, 4*6));
movq(Address(rsp, _CTX), CTX); // store
bind(loop0);
@ -977,7 +979,7 @@ bind(only_one_block);
movl(d, Address(CTX, 4*3)); // 0xa54ff53a
movl(e, Address(CTX, 4*4)); // 0x510e527f
movl(f, Address(CTX, 4*5)); // 0x9b05688c
movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
// load g - r10 after use as scratch
movl(h, Address(CTX, 4*7)); // 0x5be0cd19
@ -986,6 +988,8 @@ bind(only_one_block);
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
movq(Address(rsp, _CTX), CTX);
jmpb(do_last_block);
@ -1154,9 +1158,8 @@ void MacroAssembler::sha512_AVX2_one_round_and_schedule(
// Move to appropriate lanes for calculating w[16] and w[17]
vperm2f128(xmm4, xmm0, xmm0, 0); //xmm4 = W[-16] + W[-7] + s0{ BABA }
address MASK_YMM_LO = StubRoutines::x86::pshuffle_byte_flip_mask_addr_sha512();
//Move to appropriate lanes for calculating w[18] and w[19]
vpand(xmm0, xmm0, ExternalAddress(MASK_YMM_LO + 32), AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
vpand(xmm0, xmm0, xmm10, AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
//Calculate w[16] and w[17] in both 128 bit lanes
//Calculate sigma1 for w[16] and w[17] on both 128 bit lanes
vperm2f128(xmm2, xmm7, xmm7, 17); //xmm2 = W[-2] {BABA}
@ -1250,6 +1253,7 @@ void MacroAssembler::sha512_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste
const XMMRegister& XFER = xmm0; // YTMP0
const XMMRegister& BYTE_FLIP_MASK = xmm9; // ymm9
const XMMRegister& YMM_MASK_LO = xmm10; // ymm10
#ifdef _WIN64
const Register& INP = rcx; //1st arg
const Register& CTX = rdx; //2nd arg
@ -1368,11 +1372,14 @@ void MacroAssembler::sha512_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste
movq(d, Address(CTX, 8 * 3));
movq(e, Address(CTX, 8 * 4));
movq(f, Address(CTX, 8 * 5));
movq(g, Address(CTX, 8 * 6));
// load g - r10 after it is used as scratch
movq(h, Address(CTX, 8 * 7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask_sha512;
vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); //PSHUFFLE_BYTE_FLIP_MASK wrt rip
vmovdqu(YMM_MASK_LO, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));
movq(g, Address(CTX, 8 * 6));
bind(loop0);
lea(TBL, ExternalAddress(K512_W));

View File

@ -3207,7 +3207,7 @@ class StubGenerator: public StubCodeGenerator {
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
const Register len_reg = r10; // pick the first volatile windows register
const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@ -3404,7 +3404,7 @@ class StubGenerator: public StubCodeGenerator {
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
const Register len_reg = r10; // pick the first volatile windows register
const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@ -3930,7 +3930,7 @@ class StubGenerator: public StubCodeGenerator {
__ push(rbx); // Save RBX
__ movdqu(xmm_curr_counter, Address(counter, 0x00)); // initialize counter with initial counter
__ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()));
__ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()), pos); // pos as scratch
__ pshufb(xmm_curr_counter, xmm_counter_shuf_mask); //counter is shuffled
__ movptr(pos, 0);
@ -3953,7 +3953,7 @@ class StubGenerator: public StubCodeGenerator {
__ movl(Address(used_addr, 0), used);
// key length could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()), rbx); // rbx as scratch
__ movl(rbx, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
__ cmpl(rbx, 52);
__ jcc(Assembler::equal, L_multiBlock_loopTop[1]);

View File

@ -37,6 +37,7 @@ import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
/**
* A format-agnostic container class that holds various components of a binary.
@ -257,9 +258,9 @@ public class BinaryContainer implements SymbolTable {
* prefix {@code prefix}. It also initializes internal code container, symbol table and
* relocation tables.
*/
public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
this.codeSegmentSize = config.codeSegmentSize;
this.codeEntryAlignment = config.codeEntryAlignment;
public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
// read only, code
codeContainer = new CodeContainer(".text", this);
@ -289,30 +290,31 @@ public class BinaryContainer implements SymbolTable {
addGlobalSymbols();
recordConfiguration(config);
recordConfiguration(graalHotSpotVMConfig, graphBuilderConfig);
}
private void recordConfiguration(GraalHotSpotVMConfig config) {
private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig) {
// @formatter:off
boolean[] booleanFlags = { config.cAssertions, // Debug VM
config.useCompressedOops,
config.useCompressedClassPointers,
config.compactFields,
config.useG1GC,
config.useCMSGC,
config.useTLAB,
config.useBiasedLocking,
boolean[] booleanFlags = { graalHotSpotVMConfig.cAssertions, // Debug VM
graalHotSpotVMConfig.useCompressedOops,
graalHotSpotVMConfig.useCompressedClassPointers,
graalHotSpotVMConfig.compactFields,
graalHotSpotVMConfig.useG1GC,
graalHotSpotVMConfig.useCMSGC,
graalHotSpotVMConfig.useTLAB,
graalHotSpotVMConfig.useBiasedLocking,
TieredAOT.getValue(),
config.enableContended,
config.restrictContended,
graalHotSpotVMConfig.enableContended,
graalHotSpotVMConfig.restrictContended,
graphBuilderConfig.omitAssertions()
};
int[] intFlags = { config.narrowOopShift,
config.narrowKlassShift,
config.contendedPaddingWidth,
config.fieldsAllocationStyle,
config.objectAlignment,
config.codeSegmentSize,
int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift,
graalHotSpotVMConfig.getKlassEncoding().shift,
graalHotSpotVMConfig.contendedPaddingWidth,
graalHotSpotVMConfig.fieldsAllocationStyle,
1 << graalHotSpotVMConfig.getOopEncoding().alignment,
graalHotSpotVMConfig.codeSegmentSize,
};
// @formatter:on
@ -395,6 +397,10 @@ public class BinaryContainer implements SymbolTable {
return "_aot_narrow_klass_base_address";
}
public String getNarrowOopBaseAddressSymbolName() {
return "_aot_narrow_oop_base_address";
}
public String getLogOfHeapRegionGrainBytesSymbolName() {
return "_aot_log_of_heap_region_grain_bytes";
}
@ -445,6 +451,7 @@ public class BinaryContainer implements SymbolTable {
createGotSymbol(getHeapTopAddressSymbolName());
createGotSymbol(getHeapEndAddressSymbolName());
createGotSymbol(getNarrowKlassBaseAddressSymbolName());
createGotSymbol(getNarrowOopBaseAddressSymbolName());
createGotSymbol(getPollingPageSymbolName());
createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());

View File

@ -77,10 +77,14 @@ public class AOTBackend {
this.filters = filters;
providers = backend.getProviders();
codeCache = providers.getCodeCache();
graphBuilderSuite = initGraphBuilderSuite(backend);
graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
}
public PhaseSuite<HighTierContext> getGraphBuilderSuite() {
return graphBuilderSuite;
}
private Suites getSuites() {
// create suites every time, as we modify options for the compiler
return backend.getSuites().getDefaultSuites();
@ -146,14 +150,14 @@ public class AOTBackend {
return backend.getRuntime().getVMConfig().cAssertions;
}
private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend) {
private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
// Use all default plugins.
Plugins plugins = baseConfig.getPlugins();
GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
iterator.next();
iterator.remove();

View File

@ -293,12 +293,18 @@ public class AOTCompiledClass {
// Record methods holder
methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
// Record inlinee classes
for (ResolvedJavaMethod m : methodInfo.getCompilationResult().getMethods()) {
methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
ResolvedJavaMethod[] inlinees = methodInfo.getCompilationResult().getMethods();
if (inlinees != null) {
for (ResolvedJavaMethod m : inlinees) {
methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
}
}
// Record classes of fields that were accessed
for (ResolvedJavaField f : methodInfo.getCompilationResult().getFields()) {
methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
ResolvedJavaField[] fields = methodInfo.getCompilationResult().getFields();
if (fields != null) {
for (ResolvedJavaField f : fields) {
methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
}
}
}
}

View File

@ -0,0 +1,64 @@
package jdk.tools.jaotc;/*
* Copyright (c) 2015, 2017, 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.
*/
public class LoadedClass {
private final String name;
private final Class<?> clz;
public LoadedClass(String name, Class<?> clz) {
this.name = name;
this.clz = clz;
}
public String getName() {
return name;
}
public Class<?> getLoadedClass() {
return clz;
}
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof LoadedClass)) return false;
LoadedClass that = (LoadedClass) o;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return clz != null ? clz.equals(that.clz) : that.clz == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (clz != null ? clz.hashCode() : 0);
return result;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -43,19 +43,31 @@ import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.stream.Stream;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.collect.ClassCollector;
import jdk.tools.jaotc.collect.*;
import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
import jdk.tools.jaotc.collect.jar.JarSourceProvider;
import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
import jdk.tools.jaotc.utils.Timer;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.runtime.RuntimeProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
@ -120,17 +132,7 @@ public class Main implements LogPrinter {
abstract void process(Main task, String opt, String arg) throws BadArgs;
}
static Option[] recognizedOptions = {new Option(" --module <name> Module to compile", true, "--module") {
@Override
void process(Main task, String opt, String arg) {
task.options.module = arg;
}
}, new Option(" --module-path <path> Specify where to find module to compile", true, "--module-path") {
@Override
void process(Main task, String opt, String arg) {
task.options.modulepath = arg;
}
}, new Option(" --output <file> Output file name", true, "--output") {
static Option[] recognizedOptions = { new Option(" --output <file> Output file name", true, "--output") {
@Override
void process(Main task, String opt, String arg) {
String name = arg;
@ -139,22 +141,48 @@ public class Main implements LogPrinter {
}
task.options.outputName = name;
}
}, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
}
}, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
}
}, new Option(" --module <modules> List of modules to compile", true, "--module") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
}
}, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
}
}, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") {
@Override
void process(Main task, String opt, String arg) {
String[] elements = arg.split(":");
task.options.searchPath.add(elements);
}
}, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
@Override
void process(Main task, String opt, String arg) {
task.options.methodList = arg;
}
}, new Option(" --compile-for-tiered Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
}, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
@Override
void process(Main task, String opt, String arg) {
TieredAOT.setValue(true);
}
}, new Option(" --classpath <path> Specify where to find user class files", true, "--classpath", "--class-path") {
}, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
@Override
void process(Main task, String opt, String arg) {
task.options.classpath = arg;
task.options.compileWithAssertions = true;
}
}, new Option(" --threads <number> Number of compilation threads to be used", true, "--threads") {
}, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
@Override
void process(Main task, String opt, String arg) {
int threads = Integer.parseInt(arg);
@ -213,27 +241,27 @@ public class Main implements LogPrinter {
}};
public static class Options {
public List<String> files = new LinkedList<>();
public String module = null;
public String modulepath = "modules";
public List<SearchFor> files = new LinkedList<>();
public String outputName = "unnamed";
public String methodList;
public String classpath = ".";
public List<ClassSource> sources = new ArrayList<>();
public SearchPath searchPath = new SearchPath();
/**
* We don't see scaling beyond 16 threads.
*/
private static final int COMPILER_THREADS = 16;
int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
public boolean ignoreClassLoadingErrors;
public boolean exitOnError;
boolean info;
boolean verbose;
boolean debug;
boolean help;
boolean version;
public boolean info;
public boolean verbose;
public boolean debug;
public boolean help;
public boolean version;
public boolean compileWithAssertions;
}
/* package */final Options options = new Options();
@ -275,7 +303,9 @@ public class Main implements LogPrinter {
printlnInfo("Compiling " + options.outputName + "...");
final long start = System.currentTimeMillis();
run();
if (!run()) {
return EXIT_ABNORMAL;
}
final long end = System.currentTimeMillis();
printlnInfo("Total time: " + (end - start) + " ms");
@ -318,17 +348,34 @@ public class Main implements LogPrinter {
}
@SuppressWarnings("try")
private void run() throws Exception {
private boolean run() throws Exception {
openLog();
try {
CompilationSpec compilationRestrictions = collectSpecifiedMethods();
Set<Class<?>> classesToCompile;
Set<Class<?>> classesToCompile = new HashSet<>();
try (Timer t = new Timer(this, "")) {
ClassCollector collector = new ClassCollector(this.options, this);
classesToCompile = collector.collectClassesToCompile();
FileSupport fileSupport = new FileSupport();
ClassSearch lookup = new ClassSearch();
lookup.addProvider(new ModuleSourceProvider());
lookup.addProvider(new ClassNameSourceProvider(fileSupport));
lookup.addProvider(new JarSourceProvider());
lookup.addProvider(new DirectorySourceProvider(fileSupport));
List<LoadedClass> found = null;
try {
found = lookup.search(options.files, options.searchPath);
} catch (InternalError e) {
reportError(e);
return false;
}
for (LoadedClass loadedClass : found) {
classesToCompile.add(loadedClass.getLoadedClass());
}
printInfo(classesToCompile.size() + " classes found");
}
@ -356,6 +403,11 @@ public class Main implements LogPrinter {
AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
classes = compiler.compileClasses(classes);
GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
@ -364,7 +416,7 @@ public class Main implements LogPrinter {
System.gc();
}
BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
dataBuilder.prepareData();
@ -446,6 +498,7 @@ public class Main implements LogPrinter {
} finally {
closeLog();
}
return true;
}
private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
@ -509,7 +562,7 @@ public class Main implements LogPrinter {
break;
}
} else {
options.files.add(arg);
options.files.add(new SearchFor(arg));
}
}
}
@ -570,6 +623,12 @@ public class Main implements LogPrinter {
log.flush();
}
private void reportError(Throwable e) {
log.println("Error: " + e.getMessage());
e.printStackTrace(log);
log.flush();
}
private void reportError(String key, Object... args) {
printError(MessageFormat.format(key, args));
}
@ -580,17 +639,17 @@ public class Main implements LogPrinter {
}
private void showUsage() {
log.println("Usage: " + PROGNAME + " <options> list...");
log.println("Usage: " + PROGNAME + " <options> list");
log.println("use --help for a list of possible options");
}
private void showHelp() {
log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
log.println("Usage: " + PROGNAME + " <options> list");
log.println();
log.println(" list A list of class files, jar files or directories which");
log.println(" contains class files.");
log.println(" list A : separated list of class names, modules, jar files");
log.println(" or directories which contain class files.");
log.println();
log.println("where possible options include:");
log.println("where options include:");
for (Option o : recognizedOptions) {
String name = o.aliases[0].substring(1); // there must always be at least one name
name = name.charAt(0) == '-' ? name.substring(1) : name;

View File

@ -48,6 +48,7 @@ enum MarkId {
HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
NARROW_OOP_BASE_ADDRESS("CodeInstaller::NARROW_OOP_BASE_ADDRESS"),
CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");

View File

@ -57,6 +57,7 @@ class MarkProcessor {
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
case NARROW_KLASS_BASE_ADDRESS:
case NARROW_OOP_BASE_ADDRESS:
case CRC_TABLE_ADDRESS:
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
@ -78,6 +79,9 @@ class MarkProcessor {
case NARROW_KLASS_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
break;
case NARROW_OOP_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowOopBaseAddressSymbolName();
break;
case CRC_TABLE_ADDRESS:
vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
break;

View File

@ -1,332 +0,0 @@
/*
* Copyright (c) 2016, 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 jdk.tools.jaotc.collect;
import jdk.tools.jaotc.LogPrinter;
import jdk.tools.jaotc.Main;
import java.io.File;
import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import static java.nio.file.FileVisitResult.CONTINUE;
public class ClassCollector {
private final Main.Options options;
private final LogPrinter log;
public ClassCollector(Main.Options options, LogPrinter log) {
this.options = options;
this.log = log;
}
/**
* Collect all class names passed by the user.
*
* @return array list of classes
*/
public Set<Class<?>> collectClassesToCompile() {
Set<Class<?>> classes = new HashSet<>();
List<String> filesToScan = new LinkedList<>(options.files);
if (options.module != null) {
classes.addAll(scanModule(filesToScan));
}
classes.addAll(scanFiles(filesToScan));
return classes;
}
private Set<Class<?>> scanModule(List<String> filesToScan) {
String module = options.module;
// Search module in standard JDK installation.
Path dir = getModuleDirectory(options.modulepath, module);
if (Files.isDirectory(dir)) {
return loadFromModuleDirectory(dir);
} else {
findFilesToScan(filesToScan, module);
return new HashSet<>();
}
}
private Set<Class<?>> loadFromModuleDirectory(Path dir) {
log.printInfo("Scanning module: " + dir + " ...");
log.printlnVerbose(" "); // Break line
FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
Set<Class<?>> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
log.printlnInfo(" " + cls.size() + " classes loaded.");
return cls;
}
private void findFilesToScan(List<String> filesToScan, String module) {
// Try to search regular directory, .jar or .class files
Path path = Paths.get(options.modulepath, module);
if (Files.isDirectory(path)) {
filesToScan.add(".");
options.classpath = path.toString();
} else if (path.endsWith(".jar") || path.endsWith(".class")) {
filesToScan.add(path.toString());
} else {
path = Paths.get(options.modulepath, module + ".jar");
if (Files.exists(path)) {
filesToScan.add(path.toString());
} else {
path = Paths.get(options.modulepath, module + ".class");
if (Files.exists(path)) {
filesToScan.add(path.toString());
} else {
throw new InternalError("Expecting a .class, .jar or directory: " + path);
}
}
}
}
private boolean entryIsClassFile(String entry) {
return entry.endsWith(".class") && !entry.endsWith("module-info.class");
}
private Set<Class<?>> scanFiles(List<String> filesToScan) {
Set<Class<?>> classes = new HashSet<>();
for (String fileName : filesToScan) {
Set<Class<?>> loaded = scanFile(fileName);
log.printlnInfo(" " + loaded.size() + " classes loaded.");
classes.addAll(loaded);
}
return classes;
}
interface ClassLoaderFactory {
ClassLoader create() throws IOException;
}
private Set<Class<?>> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
ClassLoader loader = null;
try {
loader = factory.create();
return loadClassFiles(root, finder, loader);
} catch (IOException e) {
throw new InternalError(e);
} finally {
if (loader instanceof AutoCloseable) {
try {
((AutoCloseable) loader).close();
} catch (Exception e) {
throw new InternalError(e);
}
}
}
}
private Set<Class<?>> scanFile(String fileName) {
log.printInfo("Scanning: " + fileName + " ...");
log.printlnVerbose(" "); // Break line
if (fileName.endsWith(".jar")) {
return loadFromJarFile(fileName);
} else if (fileName.endsWith(".class")) {
Set<Class<?>> classes = new HashSet<>();
loadFromClassFile(fileName, classes);
return classes;
} else {
return scanClassPath(fileName);
}
}
private Set<Class<?>> loadFromJarFile(String fileName) {
FileSystem fs = makeFileSystem(fileName);
FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
}
private void loadFromClassFile(String fileName, Set<Class<?>> classes) {
Class<?> result;
File file = new File(options.classpath);
try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
result = loadClassFile(loader, fileName);
} catch (IOException e) {
throw new InternalError(e);
}
Class<?> c = result;
addClass(classes, fileName, c);
}
private Set<Class<?>> scanClassPath(String fileName) {
Path classPath = Paths.get(options.classpath);
if (!Files.exists(classPath)) {
throw new InternalError("Path does not exist: " + classPath);
}
if (!Files.isDirectory(classPath)) {
throw new InternalError("Path must be a directory: " + classPath);
}
// Combine class path and file name and see what it is.
Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
if (combinedPath.endsWith(".class")) {
throw new InternalError("unimplemented");
} else if (Files.isDirectory(combinedPath)) {
return scanDirectory(classPath, combinedPath);
} else {
throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
}
}
private FileSystem makeFileSystem(String fileName) {
try {
return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
} catch (IOException e) {
throw new InternalError(e);
}
}
private URI makeJarFileURI(String fileName) {
try {
return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
} catch (URISyntaxException e) {
throw new InternalError(e);
}
}
private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
return path -> m1.matches(path) && m2.matches(path);
}
private Set<Class<?>> scanDirectory(Path classPath, Path combinedPath) {
String dir = options.classpath;
FileSystem fileSystem = FileSystems.getDefault();
PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
FileSystemFinder finder = new FileSystemFinder(combinedPath,
combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
File file = new File(dir);
try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
return loadClassFiles(classPath, finder, loader);
} catch (IOException e) {
throw new InternalError(e);
}
}
private Set<Class<?>> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
Set<Class<?>> classes = new HashSet<>();
for (Path name : finder.done()) {
// Now relativize to the class path so we get the actual class names.
String entry = root.relativize(name).normalize().toString();
Class<?> c = loadClassFile(loader, entry);
addClass(classes, entry, c);
}
return classes;
}
private void addClass(Set<Class<?>> classes, String name, Class<?> c) {
if (c != null) {
classes.add(c);
log.printlnVerbose(" loaded " + name);
}
}
private URL[] buildUrls(String fileName) throws MalformedURLException {
return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
}
private URL[] buildUrls(File file) throws MalformedURLException {
return new URL[] {file.toURI().toURL() };
}
private Path getModuleDirectory(String modulepath, String module) {
FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
return fs.getPath(modulepath, module);
}
/**
* Loads a class with the given file name from the specified {@link URLClassLoader}.
*/
private Class<?> loadClassFile(final ClassLoader loader, final String fileName) {
int start = 0;
if (fileName.startsWith("/")) {
start = 1;
}
String className = fileName.substring(start, fileName.length() - ".class".length());
className = className.replace('/', '.');
try {
return loader.loadClass(className);
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (options.ignoreClassLoadingErrors) {
log.printError(className + ": " + e);
return null;
}
throw new InternalError(e);
}
}
/**
* {@link FileVisitor} implementation to find class files recursively.
*/
private static class FileSystemFinder extends SimpleFileVisitor<Path> {
private final ArrayList<Path> fileNames = new ArrayList<>();
private final PathMatcher filter;
FileSystemFinder(Path combinedPath, PathMatcher filter) {
this.filter = filter;
try {
Files.walkFileTree(combinedPath, this);
} catch (IOException e) {
throw new InternalError(e);
}
}
/**
* Compares the glob pattern against the file name.
*/
void find(Path file) {
Path name = file.getFileName();
if (name != null && filter.matches(name)) {
fileNames.add(file);
}
}
List<Path> done() {
return fileNames;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
import jdk.tools.jaotc.LoadedClass;
import java.util.ArrayList;
import java.util.List;
public class ClassSearch {
private List<SourceProvider> providers = new ArrayList<>();
public void addProvider(SourceProvider provider) {
providers.add(provider);
}
public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
List<LoadedClass> loaded = new ArrayList<>();
List<ClassSource> sources = new ArrayList<>();
for (SearchFor entry : search) {
sources.add(findSource(entry, searchPath));
}
for (ClassSource source : sources) {
source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
}
return loaded;
}
private LoadedClass loadClass(String name, ClassLoader loader) {
try {
Class<?> clzz = loader.loadClass(name);
return new LoadedClass(name, clzz);
} catch (ClassNotFoundException e) {
throw new InternalError("Failed to load with: " + loader, e);
}
}
private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
ClassSource found = null;
for (SourceProvider provider : providers) {
if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
continue;
}
ClassSource source = provider.findSource(searchFor.getName(), searchPath);
if (source != null) {
if (found != null) {
throw new InternalError("Multiple possible sources: " + source + " and: " + found);
}
found = source;
}
}
if (found == null) {
throw new InternalError("Failed to find: " + searchFor.toString());
}
return found;
}
public static List<SearchFor> makeList(String type, String argument) {
List<SearchFor> list = new ArrayList<>();
String[] elements = argument.split(":");
for (String element : elements) {
list.add(new SearchFor(element, type));
}
return list;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public interface ClassSource {
static boolean pathIsClassFile(Path entry) {
String fileName = entry.getFileName().toString();
return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
}
static String makeClassName(Path path) {
String fileName = path.toString();
if (!fileName.endsWith(".class")) {
throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
}
int start = 0;
if (fileName.startsWith("/")) {
start = 1;
}
String className = fileName.substring(start, fileName.length() - ".class".length());
className = className.replace('/', '.');
return className;
}
void eachClass(BiConsumer<String, ClassLoader> consumer);
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.util.HashMap;
public class FileSupport {
public boolean exists(Path path) {
return Files.exists(path);
}
public boolean isDirectory(Path path) {
return Files.isDirectory(path);
}
private FileSystem makeJarFileSystem(Path path) {
try {
return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
} catch (IOException e) {
throw new InternalError(e);
}
}
private URI makeJarFileURI(Path path) {
try {
return new URI("jar:file:" + path.toAbsolutePath() + "!/");
} catch (URISyntaxException e) {
throw new InternalError(e);
}
}
public ClassLoader createClassLoader(Path path, ClassLoader parent) {
try {
return URLClassLoader.newInstance(buildUrls(path), parent);
} catch (MalformedURLException e) {
throw new InternalError(e);
}
}
public ClassLoader createClassLoader(Path path) throws MalformedURLException {
return URLClassLoader.newInstance(buildUrls(path));
}
private URL[] buildUrls(Path path) throws MalformedURLException {
return new URL[] { path.toUri().toURL() };
}
public Path getJarFileSystemRoot(Path jarFile) {
FileSystem fileSystem = makeJarFileSystem(jarFile);
return fileSystem.getPath("/");
}
public boolean isAbsolute(Path entry) {
return entry.isAbsolute();
}
public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root,null);
for (Path entry : paths) {
Path relative = root.relativize(entry);
if (relative.equals(path)) {
return entry;
}
}
return null;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Iterator;
import static java.nio.file.FileVisitResult.CONTINUE;
/**
* {@link FileVisitor} implementation to find class files recursively.
*/
public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
private final ArrayList<Path> fileNames = new ArrayList<>();
private final PathMatcher filter;
public FileSystemFinder(Path combinedPath, PathMatcher filter) {
this.filter = filter;
try {
Files.walkFileTree(combinedPath, this);
} catch (IOException e) {
throw new InternalError(e);
}
}
/**
* Compares the glob pattern against the file name.
*/
private void find(Path file) {
Path name = file.getFileName();
if (name != null && filter.matches(name)) {
fileNames.add(file);
}
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
@Override
public Iterator<Path> iterator() {
return fileNames.iterator();
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
public class SearchFor {
private final String name;
private final String type;
public SearchFor(String name) {
this(name, "unknown");
}
public SearchFor(String name, String type) {
this.name = name;
this.type = type;
}
public boolean isUnknown() {
return "unknown".equals(type);
}
public String getType() {
return this.type;
}
public String getName() {
return this.name;
}
@Override
public String toString() {
return type + ":" + name;
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class SearchPath {
private final List<Path> searchPaths = new ArrayList<>();
private final FileSupport fileSupport;
public SearchPath() {
this(new FileSupport());
}
public SearchPath(FileSupport fileSupport) {
this.fileSupport = fileSupport;
}
public Path find(FileSystem fileSystem, Path entry, String... defaults) {
if (isAbsolute(entry)) {
if (exists(entry)) {
return entry;
}
return null;
}
if (exists(entry)) {
return entry;
}
for (String searchPath : defaults) {
Path newPath = fileSystem.getPath(searchPath, entry.toString());
if (exists(newPath)) {
return newPath;
}
}
for (Path searchPath : searchPaths) {
Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
if (exists(newPath)) {
return newPath;
}
}
return null;
}
private boolean isAbsolute(Path entry) {
return fileSupport.isAbsolute(entry);
}
private boolean exists(Path entry) {
return fileSupport.exists(entry);
}
public void add(String... paths) {
for (String name : paths) {
Path path = Paths.get(name);
searchPaths.add(path);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
public interface SourceProvider {
ClassSource findSource(String name, SearchPath searchPath);
boolean supports(String type);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
import java.util.function.BiConsumer;
public class ClassNameSource implements ClassSource {
private final String name;
private final ClassLoader classLoader;
public ClassNameSource(String name, ClassLoader classLoader) {
this.name = name;
this.classLoader = classLoader;
}
@Override
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
consumer.accept(name, classLoader);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSupport;
import jdk.tools.jaotc.collect.SearchPath;
import jdk.tools.jaotc.collect.SourceProvider;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ClassNameSourceProvider implements SourceProvider {
public final static String TYPE = "classname";
private final ClassLoader classLoader;
public ClassNameSourceProvider(FileSupport fileSupport) {
String classPath = System.getProperty("java.class.path");
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if (classPath != null && !classPath.isEmpty()) {
classLoader = systemClassLoader;
} else {
Path path = Paths.get(".").toAbsolutePath();
classLoader = fileSupport.createClassLoader(path, systemClassLoader);
}
}
@Override
public ClassSource findSource(String name, SearchPath searchPath) {
try {
classLoader.loadClass(name);
return new ClassNameSource(name, classLoader);
} catch (ClassNotFoundException e) {
return null;
}
}
@Override
public boolean supports(String type) {
return TYPE.equals(type);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class DirectorySource implements ClassSource {
private final Path directoryPath;
private final ClassLoader classLoader;
public DirectorySource(Path directoryPath, ClassLoader classLoader) {
this.directoryPath = directoryPath;
this.classLoader = classLoader;
}
@Override
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
for (Path path : finder) {
consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
}
}
@Override
public String toString() {
return "directory:" + directoryPath.toString();
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSupport;
import jdk.tools.jaotc.collect.SearchPath;
import jdk.tools.jaotc.collect.SourceProvider;
import java.net.MalformedURLException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class DirectorySourceProvider implements SourceProvider {
private final FileSupport fileSupport;
private final FileSystem fileSystem;
public final static String TYPE = "directory";
public DirectorySourceProvider(FileSupport fileSupport) {
this.fileSupport = fileSupport;
fileSystem = FileSystems.getDefault();
}
@Override
public ClassSource findSource(String name, SearchPath searchPath) {
Path directoryPath = fileSystem.getPath(name);
if (!fileSupport.exists(directoryPath)) {
return null;
}
if (!fileSupport.isDirectory(directoryPath)) {
return null;
}
try {
ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
return new DirectorySource(directoryPath, classLoader);
} catch (MalformedURLException e) {
return null;
}
}
@Override
public boolean supports(String type) {
return TYPE.equals(type);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class JarFileSource implements ClassSource {
private final Path jarFile;
private final Path jarRootPath;
private final ClassLoader classLoader;
public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
this.jarFile = jarFile;
this.jarRootPath = jarRootPath;
this.classLoader = classLoader;
}
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
for (Path path : finder) {
consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
}
}
@Override
public String toString() {
return "jar:" + jarFile.toString();
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSupport;
import jdk.tools.jaotc.collect.SearchPath;
import jdk.tools.jaotc.collect.SourceProvider;
import java.net.MalformedURLException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.ProviderNotFoundException;
public class JarSourceProvider implements SourceProvider {
private final FileSystem fileSystem;
private final FileSupport fileSupport;
public final static String TYPE = "jar";
public JarSourceProvider() {
this(new FileSupport());
}
public JarSourceProvider(FileSupport fileSupport) {
this.fileSupport = fileSupport;
fileSystem = FileSystems.getDefault();
}
@Override
public ClassSource findSource(String name, SearchPath searchPath) {
Path fileName = fileSystem.getPath(name);
Path jarFile = searchPath.find(fileSystem, fileName);
if (!validPath(jarFile)) {
return null;
}
return createSource(jarFile);
}
private ClassSource createSource(Path jarFile) {
try {
Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
if (jarRootPath == null) {
return null;
}
ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
return new JarFileSource(jarFile, jarRootPath, classLoader);
} catch (ProviderNotFoundException | MalformedURLException e) {
}
return null;
}
@Override
public boolean supports(String type) {
return TYPE.equals(type);
}
private boolean validPath(Path jarFile) {
return jarFile != null && !fileSupport.isDirectory(jarFile);
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class ModuleSource implements ClassSource {
private final Path modulePath;
private final ClassLoader classLoader;
public ModuleSource(Path modulePath, ClassLoader classLoader) {
this.modulePath = modulePath;
this.classLoader = classLoader;
}
@Override
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
for (Path path : finder) {
consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
}
}
public Path getModulePath() {
return modulePath;
}
@Override
public String toString() {
return "module:" + modulePath.toString();
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.FileSupport;
import jdk.tools.jaotc.collect.SearchPath;
import jdk.tools.jaotc.collect.SourceProvider;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class ModuleSourceProvider implements SourceProvider {
private final FileSystem fileSystem;
private final ClassLoader classLoader;
private final FileSupport fileSupport;
public final static String TYPE = "module";
public ModuleSourceProvider() {
this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
}
public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
this.fileSystem = fileSystem;
this.classLoader = classLoader;
this.fileSupport = fileSupport;
}
@Override
public ClassSource findSource(String name, SearchPath searchPath) {
Path path = fileSystem.getPath(name);
Path dir = fileSystem.getPath("modules");
if (dir == null || !fileSupport.isDirectory(dir)) {
return null;
}
Path found = findModuleDirectory(dir, path);
if (found == null) {
return null;
}
return new ModuleSource(found, classLoader);
}
private Path findModuleDirectory(Path root, Path path) {
try {
return fileSupport.getSubDirectory(fileSystem, root, path);
} catch (IOException e) {
throw new InternalError(e);
}
}
@Override
public boolean supports(String type) {
return TYPE.equals(type);
}
}

View File

@ -100,15 +100,19 @@ final class CompilerToVM {
native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} can be inlined. A method may not be inlinable for a number of
* reasons such as:
* <ul>
* <li>a CompileOracle directive may prevent inlining or compilation of methods</li>
* <li>the method may have a bytecode breakpoint set</li>
* <li>the method may have other bytecode features that require special handling by the VM</li>
* </ul>
* Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
* the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
* breakpoint is currently set in {@code method} or {@code method} contains other bytecode
* features that require special handling by the VM.
*/
native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method);
native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} is targeted by a VM directive (e.g.,
* {@code -XX:CompileCommand=dontinline,<pattern>}) or annotation (e.g.,
* {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
*/
native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} should be inlined at any cost. This could be because:

View File

@ -49,13 +49,6 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
*/
boolean isForceInline();
/**
* Returns true if this method has a {@code DontInline} annotation.
*
* @return true if DontInline annotation present, false otherwise
*/
boolean isDontInline();
/**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*

View File

@ -298,15 +298,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return (getFlags() & config().methodFlagsForceInline) != 0;
}
/**
* Returns true if this method has a {@code DontInline} annotation.
*
* @return true if DontInline annotation present, false otherwise
*/
public boolean isDontInline() {
return (getFlags() & config().methodFlagsDontInline) != 0;
}
/**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*
@ -582,10 +573,15 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public boolean canBeInlined() {
if (isDontInline()) {
if (hasNeverInlineDirective()) {
return false;
}
return compilerToVM().canInlineMethod(this);
return compilerToVM().isCompilable(this);
}
@Override
public boolean hasNeverInlineDirective() {
return compilerToVM().hasNeverInlineDirective(this);
}
@Override

View File

@ -346,6 +346,13 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
*/
boolean canBeInlined();
/**
* Determines if this method is targeted by a VM directive (e.g.,
* {@code -XX:CompileCommand=dontinline,<pattern>}) or VM recognized annotation (e.g.,
* {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
*/
boolean hasNeverInlineDirective();
/**
* Returns {@code true} if the inlining of this method should be forced.
*/

View File

@ -638,6 +638,7 @@ suite = {
"annotationProcessors" : [
"GRAAL_NODEINFO_PROCESSOR",
"GRAAL_REPLACEMENTS_VERIFIER",
"GRAAL_OPTIONS_PROCESSOR",
],
"workingSets" : "Graal,Graph",
},

View File

@ -116,6 +116,7 @@ public class Debug {
public static final int INFO_LOG_LEVEL = 2;
public static final int VERBOSE_LOG_LEVEL = 3;
public static final int DETAILED_LOG_LEVEL = 4;
public static final int VERY_DETAILED_LOG_LEVEL = 5;
public static boolean isDumpEnabled(int dumpLevel) {
return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);

View File

@ -267,10 +267,15 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
if (config.useCompressedClassPointers) {
Register register = r10;
AMD64HotSpotMove.decodeKlassPointer(asm, register, providers.getRegisters().getHeapBaseRegister(), src, config.getKlassEncoding());
if (config.narrowKlassBase != 0) {
// The heap base register was destroyed above, so restore it
asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config);
if (GeneratePIC.getValue()) {
asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1));
crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS);
} else {
if (config.narrowKlassBase != 0) {
// The heap base register was destroyed above, so restore it
asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
}
}
asm.cmpq(inlineCacheKlass, register);
} else {

View File

@ -265,14 +265,21 @@ public class AMD64HotSpotMove {
}
}
public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, CompressEncoding encoding) {
public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
CompressEncoding encoding = config.getKlassEncoding();
masm.movl(register, address);
if (encoding.shift != 0) {
assert encoding.alignment == encoding.shift : "Decode algorithm is wrong";
masm.shlq(register, encoding.alignment);
}
if (encoding.base != 0) {
masm.movq(scratch, encoding.base);
if (GeneratePIC.getValue() || encoding.base != 0) {
if (GeneratePIC.getValue()) {
masm.movq(scratch, masm.getPlaceholder(-1));
crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS);
} else {
assert encoding.base != 0;
masm.movq(scratch, encoding.base);
}
masm.addq(register, scratch);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2017, 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 org.graalvm.compiler.hotspot;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig {
private final CompressEncoding aotOopEncoding;
private final CompressEncoding aotKlassEncoding;
public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) {
super(store);
// In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift.
CompressEncoding vmOopEncoding = super.getOopEncoding();
aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment);
CompressEncoding vmKlassEncoding = super.getKlassEncoding();
aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment);
assert check();
}
@Override
public CompressEncoding getOopEncoding() {
return aotOopEncoding;
}
@Override
public CompressEncoding getKlassEncoding() {
return aotKlassEncoding;
}
}

View File

@ -479,7 +479,6 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
public final int methodFlagsJfrTowrite = getConstant("Method::_jfr_towrite", Integer.class);
public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
public final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
@ -773,13 +772,14 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int MARKID_HEAP_TOP_ADDRESS = getConstant("CodeInstaller::HEAP_TOP_ADDRESS", Integer.class, 17);
public final int MARKID_HEAP_END_ADDRESS = getConstant("CodeInstaller::HEAP_END_ADDRESS", Integer.class, 18);
public final int MARKID_NARROW_KLASS_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_KLASS_BASE_ADDRESS", Integer.class, 19);
public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 20);
public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 21);
public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 22);
public final int MARKID_NARROW_OOP_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_OOP_BASE_ADDRESS", Integer.class, 20);
public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 21);
public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 22);
public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 23);
// Checkstyle: resume
private boolean check() {
protected boolean check() {
for (Field f : getClass().getDeclaredFields()) {
int modifiers = f.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {

View File

@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
@ -99,7 +100,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) {
HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
config = new GraalHotSpotVMConfig(store);
config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
CompileTheWorldOptions.overrideWithNativeOptions(config);
// Only set HotSpotPrintInlining if it still has its default value (false).

View File

@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot.meta;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode;
@ -112,11 +111,6 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin {
return true;
}
}
if (GeneratePIC.getValue()) {
if (field.isSynthetic() && field.getName().startsWith("$assertionsDisabled")) {
return tryReadField(b, field, null);
}
}
if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) {
return true;
}

View File

@ -1738,9 +1738,8 @@ public class BytecodeParser implements GraphBuilderContext {
} else {
// Intrinsic was not applied: remove intrinsic guard
// and restore the original receiver node in the arguments array
for (Node node : graph.getNewNodes(intrinsicGuard.mark)) {
GraphUtil.killCFG(node);
}
intrinsicGuard.lastInstr.setNext(null);
GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
lastInstr = intrinsicGuard.lastInstr;
args[0] = intrinsicGuard.receiver;
}

View File

@ -153,9 +153,7 @@ public class SimplifyingGraphDecoder extends GraphDecoder {
}
for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
if (!(node instanceof FixedNode) && node.hasNoUsages()) {
GraphUtil.killCFG(node);
}
GraphUtil.tryKillUnused(node);
}
}

View File

@ -506,7 +506,7 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
for (Node successor : snapshot) {
if (successor != null && successor.isAlive()) {
if (successor != survivingSuccessor) {
GraphUtil.killCFG(successor, tool);
GraphUtil.killCFG((FixedNode) successor, tool);
}
}
}
@ -566,6 +566,9 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
reduceTrivialMerge(begin);
} else { // convert to merge
AbstractMergeNode merge = this.add(new MergeNode());
for (EndNode end : begin.forwardEnds()) {
merge.addForwardEnd(end);
}
this.replaceFixedWithFixed(begin, merge);
}
}
@ -576,7 +579,14 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
for (PhiNode phi : merge.phis().snapshot()) {
assert phi.valueCount() == 1;
ValueNode singleValue = phi.valueAt(0);
phi.replaceAtUsagesAndDelete(singleValue);
if (phi.hasUsages()) {
phi.replaceAtUsagesAndDelete(singleValue);
} else {
phi.safeDelete();
if (singleValue != null) {
GraphUtil.tryKillUnused(singleValue);
}
}
}
// remove loop exits
if (merge instanceof LoopBeginNode) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2017, 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
@ -22,18 +22,30 @@
*/
package org.graalvm.compiler.nodes.util;
import static org.graalvm.compiler.graph.Graph.Options.VerifyGraalGraphEdges;
import static org.graalvm.compiler.nodes.util.GraphUtil.Options.VerifyKillCFGUnusedNodes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.common.CollectionsFactory;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeWorkList;
import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
@ -48,11 +60,15 @@ import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.LimitedValueProxy;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.ValueProxy;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValue;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodePosition;
@ -64,22 +80,78 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
public class GraphUtil {
public static void killCFG(Node node, SimplifierTool tool) {
NodeWorkList worklist = killCFG(node, tool, null);
if (worklist != null) {
for (Node successor : worklist) {
killCFG(successor, tool, worklist);
public static class Options {
@Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)//
public static final OptionValue<Boolean> VerifyKillCFGUnusedNodes = new OptionValue<>(false);
}
@SuppressWarnings("try")
public static void killCFG(FixedNode node, SimplifierTool tool) {
try (Debug.Scope scope = Debug.scope("KillCFG", node)) {
Set<Node> unusedNodes = null;
Set<Node> unsafeNodes = null;
Graph.NodeEventScope nodeEventScope = null;
if (VerifyGraalGraphEdges.getValue()) {
unsafeNodes = collectUnsafeNodes(node.graph());
}
if (VerifyKillCFGUnusedNodes.getValue()) {
Set<Node> collectedUnusedNodes = unusedNodes = CollectionsFactory.newSet();
nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
@Override
public void event(Graph.NodeEvent e, Node n) {
if (e == Graph.NodeEvent.ZERO_USAGES && isFloatingNode(n)) {
collectedUnusedNodes.add(n);
}
}
});
}
Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "Before killCFG %s", node);
NodeWorkList worklist = killCFG(node, tool, null);
if (worklist != null) {
for (Node n : worklist) {
killCFG(n, tool, worklist);
}
}
if (VerifyGraalGraphEdges.getValue()) {
Set<Node> newUnsafeNodes = collectUnsafeNodes(node.graph());
newUnsafeNodes.removeAll(unsafeNodes);
assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes;
}
if (VerifyKillCFGUnusedNodes.getValue()) {
nodeEventScope.close();
unusedNodes.removeIf(n -> n.isDeleted());
assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes;
}
} catch (Throwable t) {
throw Debug.handle(t);
}
}
/**
* Collects all node in the graph which have non-optional inputs that are null.
*/
private static Set<Node> collectUnsafeNodes(Graph graph) {
Set<Node> unsafeNodes = CollectionsFactory.newSet();
for (Node n : graph.getNodes()) {
for (Position pos : n.inputPositions()) {
Node input = pos.get(n);
if (input == null) {
if (!pos.isInputOptional()) {
unsafeNodes.add(n);
}
}
}
}
return unsafeNodes;
}
private static NodeWorkList killCFG(Node node, SimplifierTool tool, NodeWorkList worklist) {
NodeWorkList newWorklist = worklist;
// DebugScope.forceDump(node.graph(), "kill CFG %s", node);
if (node instanceof FixedNode) {
newWorklist = killCFGLinear((FixedNode) node, newWorklist, tool);
} else {
propagateKill(node);
newWorklist = propagateKill(node, newWorklist);
Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "killCFG (Floating) %s", node);
}
return newWorklist;
}
@ -93,19 +165,20 @@ public class GraphUtil {
if (current instanceof AbstractEndNode) {
// We reached a control flow end.
AbstractEndNode end = (AbstractEndNode) current;
killEnd(end, tool);
newWorklist = killEnd(end, newWorklist, tool);
} else if (current instanceof FixedWithNextNode) {
next = ((FixedWithNextNode) current).next();
// Node guaranteed to have a single successor
FixedWithNextNode fixedWithNext = (FixedWithNextNode) current;
assert fixedWithNext.successors().count() == 1 || fixedWithNext.successors().count() == 0;
assert fixedWithNext.successors().first() == fixedWithNext.next();
next = fixedWithNext.next();
} else {
// Normal control flow node.
/*
* We do not take a successor snapshot because this iterator supports concurrent
* modifications as long as they do not change the size of the successor list. Not
* taking a snapshot allows us to see modifications to other branches that may
* happen while processing one branch.
*/
// assert node.successors().count() > 1 || node.successors().count() == 0 :
// node.getClass();
Iterator<Node> successors = current.successors().iterator();
if (successors.hasNext()) {
Node first = successors.next();
@ -126,100 +199,158 @@ public class GraphUtil {
}
}
current.replaceAtPredecessor(null);
propagateKill(current);
newWorklist = propagateKill(current, newWorklist);
Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, current.graph(), "killCFGLinear %s", current);
current = next;
}
Debug.dump(Debug.DETAILED_LOG_LEVEL, in.graph(), "killCFGLinear %s", in);
return newWorklist;
}
public static void killCFG(Node node) {
public static void killCFG(FixedNode node) {
killCFG(node, null);
}
private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
/**
* Node type used temporarily while deleting loops.
*
* It is used as replacement for the loop {@link PhiNode PhiNodes} in order to break data-flow
* cycles before deleting the loop. The control-flow of the whole loop is killed before killing
* the poison node if they are still alive.
*/
@NodeInfo(allowedUsageTypes = InputType.Unchecked)
private static final class PoisonNode extends FloatingNode {
public static final NodeClass<PoisonNode> TYPE = NodeClass.create(PoisonNode.class);
protected PoisonNode() {
super(TYPE, StampFactory.forVoid());
}
}
private static NodeWorkList killEnd(AbstractEndNode end, NodeWorkList worklist, SimplifierTool tool) {
NodeWorkList newWorklist = worklist;
AbstractMergeNode merge = end.merge();
if (merge != null) {
merge.removeEnd(end);
StructuredGraph graph = end.graph();
if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) {
// dead loop
for (PhiNode phi : merge.phis().snapshot()) {
propagateKill(phi);
}
LoopBeginNode begin = (LoopBeginNode) merge;
// disconnect and delete loop ends & loop exits
for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
loopend.predecessor().replaceFirstSuccessor(loopend, null);
loopend.safeDelete();
}
begin.removeExits();
FixedNode loopBody = begin.next();
if (loopBody != null) { // for small infinite loops, the body may be killed while
// killing the loop ends
killCFG(loopBody);
// clean unused proxies to avoid creating new unused nodes
for (LoopExitNode exit : begin.loopExits()) {
for (ProxyNode vpn : exit.proxies().snapshot()) {
tryKillUnused(vpn);
}
}
begin.removeExits();
PoisonNode poison = null;
if (merge.phis().isNotEmpty()) {
poison = graph.unique(new PoisonNode());
for (PhiNode phi : merge.phis()) {
phi.replaceAtUsages(poison);
}
for (PhiNode phi : merge.phis().snapshot()) {
killWithUnusedFloatingInputs(phi);
}
}
FixedNode loopBody = begin.next();
Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, end.graph(), "killEnd (Loop) %s after initial loop cleanup", end);
if (loopBody != null) {
// for small infinite loops, the body may already be killed while killing the
// LoopEnds
newWorklist = killCFG(loopBody, tool, worklist);
}
FrameState frameState = begin.stateAfter();
begin.safeDelete();
if (frameState != null) {
tryKillUnused(frameState);
}
if (poison != null && poison.isAlive()) {
if (newWorklist == null) {
newWorklist = graph.createNodeWorkList();
}
// drain the worklist to finish the loop before adding the poison
for (Node n : newWorklist) {
killCFG(n, tool, newWorklist);
}
if (poison.isAlive()) {
newWorklist.add(poison);
}
}
} else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) {
// not a loop anymore
if (tool != null) {
merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
for (PhiNode phi : merge.phis()) {
tool.addToWorkList(phi.usages());
}
}
graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
} else if (merge.phiPredecessorCount() == 1) {
// not a merge anymore
if (tool != null) {
merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
for (PhiNode phi : merge.phis()) {
tool.addToWorkList(phi.usages());
}
}
graph.reduceTrivialMerge(merge);
}
}
return newWorklist;
}
public static boolean isFloatingNode(Node n) {
return !(n instanceof FixedNode);
}
private static void propagateKill(Node node) {
private static NodeWorkList propagateKill(Node node, NodeWorkList workList) {
NodeWorkList newWorkList = workList;
if (node != null && node.isAlive()) {
node.markDeleted();
for (Node in : node.inputs()) {
if (in.isAlive()) {
in.removeUsage(node);
if (in.hasNoUsages() && !(in instanceof FixedNode)) {
killWithUnusedFloatingInputs(in);
}
}
}
ArrayList<Node> usageToKill = null;
for (Node usage : node.usages()) {
if (usage.isAlive() && !(usage instanceof FixedNode)) {
if (usageToKill == null) {
usageToKill = new ArrayList<>();
}
usageToKill.add(usage);
}
}
if (usageToKill != null) {
for (Node usage : usageToKill) {
if (usage.isAlive()) {
if (usage instanceof PhiNode) {
PhiNode phiNode = (PhiNode) usage;
usage.replaceFirstInput(node, null);
if (phiNode.merge() == null || !phiNode.hasValidInput()) {
propagateKill(usage);
}
for (Node usage : node.usages().snapshot()) {
assert usage.isAlive();
if (isFloatingNode(usage)) {
boolean addUsage = false;
if (usage instanceof PhiNode) {
PhiNode phi = (PhiNode) usage;
assert phi.merge() != null;
if (phi.merge() == node) {
// we reach the phi directly through he merge, queue it.
addUsage = true;
} else {
propagateKill(usage);
// we reach it though a value
assert phi.values().contains(node);
// let that be handled when we reach the corresponding End node
}
} else {
addUsage = true;
}
if (addUsage) {
if (newWorkList == null) {
newWorkList = node.graph().createNodeWorkList();
}
newWorkList.add(usage);
}
}
usage.replaceFirstInput(node, null);
}
killWithUnusedFloatingInputs(node);
}
return newWorkList;
}
private static boolean checkKill(Node node) {
node.assertTrue(node.isAlive(), "must be alive");
node.assertTrue(node.hasNoUsages(), "cannot kill node %s because of usages: %s", node, node.usages());
node.assertTrue(node.predecessor() == null, "cannot kill node %s because of predecessor: %s", node, node.predecessor());
return true;
}
public static void killWithUnusedFloatingInputs(Node node) {
assert checkKill(node);
node.markDeleted();
outer: for (Node in : node.inputs()) {
if (in.isAlive()) {
@ -227,7 +358,7 @@ public class GraphUtil {
if (in.hasNoUsages()) {
node.maybeNotifyZeroUsages(in);
}
if (!(in instanceof FixedNode)) {
if (isFloatingNode(in)) {
if (in.hasNoUsages()) {
killWithUnusedFloatingInputs(in);
} else if (in instanceof PhiNode) {
@ -244,6 +375,35 @@ public class GraphUtil {
}
}
/**
* Removes all nodes created after the {@code mark}, assuming no "old" nodes point to "new"
* nodes.
*/
public static void removeNewNodes(Graph graph, Graph.Mark mark) {
assert checkNoOldToNewEdges(graph, mark);
for (Node n : graph.getNewNodes(mark)) {
n.markDeleted();
for (Node in : n.inputs()) {
in.removeUsage(n);
}
}
}
private static boolean checkNoOldToNewEdges(Graph graph, Graph.Mark mark) {
for (Node old : graph.getNodes()) {
if (graph.isNew(mark, old)) {
break;
}
for (Node n : old.successors()) {
assert !graph.isNew(mark, n) : old + " -> " + n;
}
for (Node n : old.inputs()) {
assert !graph.isNew(mark, n) : old + " -> " + n;
}
}
return true;
}
public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) {
if (fixed instanceof StateSplit) {
FrameState stateAfter = ((StateSplit) fixed).stateAfter();
@ -688,8 +848,9 @@ public class GraphUtil {
@Override
public void deleteBranch(Node branch) {
branch.predecessor().replaceFirstSuccessor(branch, null);
GraphUtil.killCFG(branch, this);
FixedNode fixedBranch = (FixedNode) branch;
fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
GraphUtil.killCFG(fixedBranch, this);
}
@Override

View File

@ -444,8 +444,9 @@ public class CanonicalizerPhase extends BasePhase<PhaseContext> {
@Override
public void deleteBranch(Node branch) {
branch.predecessor().replaceFirstSuccessor(branch, null);
GraphUtil.killCFG(branch, this);
FixedNode fixedBranch = (FixedNode) branch;
fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
GraphUtil.killCFG(fixedBranch, this);
}
@Override

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. 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
@ -632,7 +632,6 @@ void os::Aix::signal_sets_init() {
sigaddset(&unblocked_sigs, SIGBUS);
sigaddset(&unblocked_sigs, SIGFPE);
sigaddset(&unblocked_sigs, SIGTRAP);
sigaddset(&unblocked_sigs, SIGDANGER);
sigaddset(&unblocked_sigs, SR_signum);
if (!ReduceSignalUsage) {
@ -1553,6 +1552,8 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
print_signal_handler(st, SIGTRAP, buf, buflen);
// We also want to know if someone else adds a SIGDANGER handler because
// that will interfere with OOM killling.
print_signal_handler(st, SIGDANGER, buf, buflen);
}
@ -3156,7 +3157,6 @@ void os::Aix::install_signal_handlers() {
set_signal_handler(SIGFPE, true);
set_signal_handler(SIGTRAP, true);
set_signal_handler(SIGXFSZ, true);
set_signal_handler(SIGDANGER, true);
if (libjsig_is_loaded) {
// Tell libjsig jvm finishes setting signal handlers.
@ -3273,7 +3273,6 @@ void os::run_periodic_checks() {
if (UseSIGTRAP) {
DO_SIGNAL_CHECK(SIGTRAP);
}
DO_SIGNAL_CHECK(SIGDANGER);
// ReduceSignalUsage allows the user to override these handlers
// see comments at the very top and jvm_solaris.h

View File

@ -778,6 +778,11 @@ void os::set_native_thread_name(const char *name) {
// is already attached to a debugger; debugger must observe
// the exception below to show the correct name.
// If there is no debugger attached skip raising the exception
if (!IsDebuggerPresent()) {
return;
}
const DWORD MS_VC_EXCEPTION = 0x406D1388;
struct {
DWORD dwType; // must be 0x1000

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. 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
@ -258,13 +258,6 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
}
}
// Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
// space falls below 30%. This is only a chance for the process to gracefully abort.
// We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
if (sig == SIGDANGER) {
goto report_and_die;
}
if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
goto run_chained_handler;
}

View File

@ -87,6 +87,7 @@
#define SPELL_REG_FP "rbp"
#else
#define REG_FP 29
#define REG_LR 30
#define SPELL_REG_SP "sp"
#define SPELL_REG_FP "x29"
@ -182,6 +183,46 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame(sp, fp, epc.pc());
}
bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Linux::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
// interpreter performs stack banging after the fixed frame header has
// been generated while the compilers perform it before. To maintain
// semantic consistency between interpreted and compiled frames, the
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_context(uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
// In compiled code, the stack banging is performed before LR
// has been saved in the frame. LR is live, and SP and FP
// belong to the caller.
intptr_t* fp = os::Linux::ucontext_get_fp(uc);
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
address pc = (address)(uc->uc_mcontext.regs[REG_LR]
- NativeInstruction::instruction_size);
*fr = frame(sp, fp, pc);
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
assert(!fr->is_first_frame(), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
// By default, gcc always saves frame pointer rfp on this stack. This
// may get turned off by -fomit-frame-pointer.
frame os::get_sender_for_C_frame(frame* fr) {
@ -313,6 +354,24 @@ JVM_handle_linux_signal(int sig,
if (thread->in_stack_yellow_reserved_zone(addr)) {
thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be a Java frame");
frame activation =
SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
if (activation.is_interpreted_frame()) {
thread->set_reserved_stack_activation((address)(
activation.fp() + frame::interpreter_frame_initial_sp_offset));
} else {
thread->set_reserved_stack_activation((address)activation.unextended_sp());
}
return 1;
}
}
}
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);

View File

@ -144,6 +144,42 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame(sp, epc.pc());
}
bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Linux::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
// Interpreter performs stack banging after the fixed frame header has
// been generated while the compilers perform it before. To maintain
// semantic consistency between interpreted and compiled frames, the
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_context(uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// More complex code with compiled code.
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling. In compiled code, we bang before
// the frame is complete.
return false;
} else {
intptr_t* fp = os::Linux::ucontext_get_fp(uc);
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
*fr = frame(sp, (address)*sp);
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
assert(!fr->is_first_frame(), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == 0) {
// fr is the last C frame.
@ -279,13 +315,31 @@ JVM_handle_linux_signal(int sig,
if (thread->on_local_stack(addr)) {
// stack overflow
if (thread->in_stack_yellow_reserved_zone(addr)) {
thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be a Javac frame");
frame activation =
SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
if (activation.is_interpreted_frame()) {
thread->set_reserved_stack_activation((address)activation.fp());
} else {
thread->set_reserved_stack_activation((address)activation.unextended_sp());
}
return 1;
}
}
}
// Throw a stack overflow exception.
// Guard pages will be reenabled while unwinding the stack.
thread->disable_stack_yellow_reserved_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
thread->disable_stack_yellow_reserved_zone();
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {

View File

@ -89,7 +89,10 @@
// Minimum usable stack sizes required to get to user code. Space for
// HotSpot guard pages is added later.
#ifdef _LP64
size_t os::Posix::_compiler_thread_min_stack_allowed = 202 * K;
// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
// and product VM builds (debug builds require significantly less stack space).
size_t os::Posix::_compiler_thread_min_stack_allowed = 325 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
#else

View File

@ -650,6 +650,7 @@ bool InstructForm::is_wide_memory_kill(FormDict &globals) const {
if( strcmp(_matrule->_opType,"MemBarReleaseLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarAcquireLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarStoreStore") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarVolatile") == 0 ) return true;
if( strcmp(_matrule->_opType,"StoreFence") == 0 ) return true;
if( strcmp(_matrule->_opType,"LoadFence") == 0 ) return true;

View File

@ -25,6 +25,7 @@
#include "aot/aotCodeHeap.hpp"
#include "aot/aotLoader.hpp"
#include "classfile/javaAssertions.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/shared/gcLocker.hpp"
#include "interpreter/abstractInterpreter.hpp"
@ -294,6 +295,8 @@ void AOTCodeHeap::publish_aot(const methodHandle& mh, AOTMethodData* method_data
// When the AOT compiler compiles something big we fail to generate metadata
// in CodeInstaller::gather_metadata. In that case the scopes_pcs_begin == scopes_pcs_end.
// In all successful cases we always have 2 entries of scope pcs.
log_info(aot, class, resolve)("Failed to load %s (no metadata available)", mh->name_and_sig_as_C_string());
_code_to_aot[code_id]._state = invalid;
return;
}
@ -536,6 +539,7 @@ void AOTCodeHeap::link_global_lib_symbols() {
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_end_address", address, (heap->supports_inline_contig_alloc() ? heap->end_addr() : NULL));
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_polling_page", address, os::get_polling_page());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, Universe::narrow_klass_base());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_oop_base_address", address, Universe::narrow_oop_base());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_inline_contiguous_allocation_supported", bool, heap->supports_inline_contig_alloc());
link_shared_runtime_symbols();
@ -706,6 +710,12 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) {
return false;
}
if (_lib->config()->_omitAssertions && JavaAssertions::enabled(kh->name()->as_C_string(), kh->class_loader() == NULL)) {
log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", kh->internal_name(), _lib->name());
sweep_dependent_methods(klass_data);
return false;
}
NOT_PRODUCT( aot_klasses_found++; )
log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread));
@ -714,7 +724,7 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) {
// Set klass's Resolve (second) got cell.
_metaspace_got[klass_data->_got_index] = kh();
// Initialize global symbols of the DSO to the correspondingVM symbol values.
// Initialize global symbols of the DSO to the corresponding VM symbol values.
link_global_lib_symbols();
int methods_offset = klass_data->_compiled_methods_offset;

View File

@ -88,7 +88,7 @@ typedef struct {
} AOTHeader;
typedef struct {
enum { CONFIG_SIZE = 11 + 7 * 4 };
enum { CONFIG_SIZE = 12 + 7 * 4 };
int _config_size;
int _narrowOopShift;
int _narrowKlassShift;
@ -108,6 +108,7 @@ typedef struct {
bool _tieredAOT;
bool _enableContended;
bool _restrictContended;
bool _omitAssertions;
} AOTConfiguration;
class AOTLib : public CHeapObj<mtCode> {

View File

@ -3298,7 +3298,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// for osr compile, bailout if some requirements are not fulfilled
if (osr_bci != -1) {
BlockBegin* osr_block = blm.bci2block()->at(osr_bci);
assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile");
if (!osr_block->is_set(BlockBegin::was_visited_flag)) {
BAILOUT("osr entry must have been visited for osr compile");
}
// check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points
if (!osr_block->state()->stack_is_empty()) {

View File

@ -895,8 +895,32 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
ciKlass* holder = s.get_declared_method_holder();
assert(declared_signature != NULL, "cannot be null");
// Push appendix argument, if one.
if (s.has_appendix()) {
// If the current bytecode has an attached appendix argument,
// push an unknown object to represent that argument. (Analysis
// of dynamic call sites, especially invokehandle calls, needs
// the appendix argument on the stack, in addition to "regular" arguments
// pushed onto the stack by bytecode instructions preceding the call.)
//
// The escape analyzer does _not_ use the ciBytecodeStream::has_appendix(s)
// method to determine whether the current bytecode has an appendix argument.
// The has_appendix() method obtains the appendix from the
// ConstantPoolCacheEntry::_f1 field, which can happen concurrently with
// resolution of dynamic call sites. Callees in the
// ciBytecodeStream::get_method() call above also access the _f1 field;
// interleaving the get_method() and has_appendix() calls in the current
// method with call site resolution can lead to an inconsistent view of
// the current method's argument count. In particular, some interleaving(s)
// can cause the method's argument count to not include the appendix, which
// then leads to stack over-/underflow in the escape analyzer.
//
// Instead of pushing the argument if has_appendix() is true, the escape analyzer
// pushes an appendix for all call sites targeted by invokedynamic and invokehandle
// instructions, except if the call site is the _invokeBasic intrinsic
// (that intrinsic is always targeted by an invokehandle instruction but does
// not have an appendix argument).
if (target->is_loaded() &&
Bytecodes::has_optional_appendix(s.cur_bc_raw()) &&
target->intrinsic_id() != vmIntrinsics::_invokeBasic) {
state.apush(unknown_obj);
}
// Pass in raw bytecode because we need to see invokehandle instructions.

View File

@ -136,15 +136,19 @@ class ciMethod : public ciMetadata {
check_is_loaded();
return _signature->size() + (_flags.is_static() ? 0 : 1);
}
// Report the number of elements on stack when invoking this method.
// This is different than the regular arg_size because invokedynamic
// has an implicit receiver.
// Report the number of elements on stack when invoking the current method.
// If the method is loaded, arg_size() gives precise information about the
// number of stack elements (using the method's signature and its flags).
// However, if the method is not loaded, the number of stack elements must
// be determined differently, as the method's flags are not yet available.
// The invoke_arg_size() method assumes in that case that all bytecodes except
// invokestatic and invokedynamic have a receiver that is also pushed onto the
// stack by the caller of the current method.
int invoke_arg_size(Bytecodes::Code code) const {
if (is_loaded()) {
return arg_size();
} else {
int arg_size = _signature->size();
// Add a receiver argument, maybe:
if (code != Bytecodes::_invokestatic &&
code != Bytecodes::_invokedynamic) {
arg_size++;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -364,7 +364,12 @@ u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TR
if (verstr != NULL) {
version = atoi(verstr);
if (version < base_version || version > cur_ver) {
is_multi_ver = false;
// If the specified version is lower than the base version, the base
// entry will be used; if the version is higher than the current
// jdk version, the highest versioned entry will be used.
if (version < base_version) {
is_multi_ver = false;
}
// print out warning, do not use assertion here since it will continue to look
// for proper version.
warning("JDK%d is not supported in multiple version jars", version);

View File

@ -94,7 +94,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
_metaspace(NULL), _unloading(false), _klasses(NULL),
_modules(NULL), _packages(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
_next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
TRACE_INIT_ID(this);

View File

@ -204,9 +204,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
// CDS
int _shared_class_loader_id;
// ReadOnly and ReadWrite metaspaces (static because only on the null
// class loader for now).
static Metaspace* _ro_metaspace;
@ -338,15 +335,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
Metaspace* rw_metaspace();
void initialize_shared_metaspaces();
int shared_class_loader_id() const {
return _shared_class_loader_id;
}
void set_shared_class_loader_id(int id) {
assert(id >= 0, "sanity");
assert(_shared_class_loader_id <0, "cannot be assigned more than once");
_shared_class_loader_id = id;
}
TRACE_DEFINE_TRACE_ID_METHODS;
};

View File

@ -163,8 +163,8 @@ void java_lang_String::compute_offsets() {
Klass* k = SystemDictionary::String_klass();
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
compute_optional_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
compute_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
initialized = true;
}
@ -3977,12 +3977,8 @@ void JavaClasses::check_offsets() {
// java.lang.String
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
if (java_lang_String::has_hash_field()) {
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
}
if (java_lang_String::has_coder_field()) {
CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
}
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
// java.lang.Class

View File

@ -81,15 +81,6 @@ class java_lang_String : AllStatic {
static Handle create_from_platform_dependent_str(const char* str, TRAPS);
static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
static bool has_hash_field() {
assert(initialized, "Must be initialized");
return (hash_offset > 0);
}
static bool has_coder_field() {
assert(initialized, "Must be initialized");
return (coder_offset > 0);
}
static void set_compact_strings(bool value);
static int value_offset_in_bytes() {

View File

@ -30,10 +30,8 @@
#include "oops/oopsHierarchy.hpp"
void java_lang_String::set_coder(oop string, jbyte coder) {
assert(initialized, "Must be initialized");
if (coder_offset > 0) {
string->byte_field_put(coder_offset, coder);
}
assert(initialized && (coder_offset > 0), "Must be initialized");
string->byte_field_put(coder_offset, coder);
}
void java_lang_String::set_value_raw(oop string, typeArrayOop buffer) {
@ -61,15 +59,11 @@ unsigned int java_lang_String::hash(oop java_string) {
return java_string->int_field(hash_offset);
}
bool java_lang_String::is_latin1(oop java_string) {
assert(initialized, "Must be initialized");
assert(initialized && (coder_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
if (coder_offset > 0) {
jbyte coder = java_string->byte_field(coder_offset);
assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
return coder == CODER_LATIN1;
} else {
return false;
}
jbyte coder = java_string->byte_field(coder_offset);
assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
return coder == CODER_LATIN1;
}
int java_lang_String::length(oop java_string) {
assert(initialized, "Must be initialized");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -39,8 +39,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
@ -48,17 +46,17 @@
#include "utilities/stringUtils.hpp"
#include "utilities/utf8.hpp"
static bool verify_module_name(char *module_name) {
static bool verify_module_name(const char *module_name) {
if (module_name == NULL) return false;
int len = (int)strlen(module_name);
return (len > 0 && len <= Symbol::max_length());
}
bool Modules::verify_package_name(char *package_name) {
bool Modules::verify_package_name(const char* package_name) {
if (package_name == NULL) return false;
int len = (int)strlen(package_name);
return (len > 0 && len <= Symbol::max_length() &&
UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
ClassFileParser::verify_unqualified_name(package_name, len,
ClassFileParser::LegalClass));
}
@ -107,10 +105,8 @@ static ModuleEntry* get_module_entry(jobject module, TRAPS) {
return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
}
static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
static PackageEntry* get_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
if (package == NULL) return NULL;
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (package_name == NULL) return NULL;
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
@ -139,7 +135,8 @@ bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
}
static void define_javabase_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS) {
jstring location, const char* const* packages,
jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
Handle module_handle(THREAD, JNIHandles::resolve(module));
@ -164,21 +161,12 @@ static void define_javabase_module(jobject module, jstring version,
}
}
objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
objArrayHandle packages_h(THREAD, packages_oop);
int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
oop string_obj = packages_h->obj_at(x);
if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Bad package name for module: " JAVA_BASE_NAME);
}
char *package_name = java_lang_String::as_utf8_string(string_obj);
const char *package_name = packages[x];
if (!Modules::verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
@ -239,7 +227,7 @@ static void define_javabase_module(jobject module, jstring version,
}
}
if (duplicate_javabase) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
THROW_MSG(vmSymbols::java_lang_InternalError(),
"Module " JAVA_BASE_NAME " is already defined");
}
@ -262,13 +250,39 @@ static void define_javabase_module(jobject module, jstring version,
}
}
// Caller needs ResourceMark.
void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
const char* package_name = package->name()->as_C_string();
if (package->module()->is_named()) {
THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
err_msg("Package %s for module %s is already in another module, %s, defined to the class loader",
package_name, module_name, package->module()->name()->as_C_string()));
} else {
THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
err_msg("Package %s for module %s is already in the unnamed module defined to the class loader",
package_name, module_name));
}
}
void Modules::define_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS) {
jstring location, const char* const* packages,
jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
if (num_packages < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"num_packages must be >= 0");
}
if (packages == NULL && num_packages > 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"num_packages should be zero if packages is null");
}
Handle module_handle(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_instance(module_handle())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
@ -283,7 +297,7 @@ void Modules::define_module(jobject module, jstring version,
// Special handling of java.base definition
if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
define_javabase_module(module, version, location, packages, CHECK);
define_javabase_module(module, version, location, packages, num_packages, CHECK);
return;
}
@ -297,21 +311,11 @@ void Modules::define_module(jobject module, jstring version,
}
Handle h_loader = Handle(THREAD, loader);
objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
objArrayHandle packages_h(THREAD, packages_oop);
int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
oop string_obj = packages_h->obj_at(x);
if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Bad package name for module: %s", module_name));
}
char *package_name = java_lang_String::as_utf8_string(string_obj);
const char* package_name = packages[x];
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: %s",
@ -323,12 +327,15 @@ void Modules::define_module(jobject module, jstring version,
!SystemDictionary::is_platform_class_loader(h_loader) &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
StringUtils::replace_no_expand(package_name, "/", ".");
size_t pkg_len = strlen(package_name);
char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
strncpy(pkg_name, package_name, pkg_len);
StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@ -347,7 +354,6 @@ void Modules::define_module(jobject module, jstring version,
// Create symbol* entry for module name.
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
int dupl_pkg_index = -1;
bool dupl_modules = false;
// Create symbol* entry for module version.
@ -373,6 +379,7 @@ void Modules::define_module(jobject module, jstring version,
assert(loader_data != NULL, "class loader data shouldn't be null");
PackageEntryTable* package_table = NULL;
PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
@ -382,13 +389,12 @@ void Modules::define_module(jobject module, jstring version,
// Check that none of the packages exist in the class loader's package table.
for (int x = 0; x < pkg_list->length(); x++) {
if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
existing_pkg = package_table->lookup_only(pkg_list->at(x));
if (existing_pkg != NULL) {
// This could be because the module was already defined. If so,
// report that error instead of the package error.
if (module_table->lookup_only(module_symbol) != NULL) {
dupl_modules = true;
} else {
dupl_pkg_index = x;
}
break;
}
@ -396,9 +402,8 @@ void Modules::define_module(jobject module, jstring version,
} // if (num_packages > 0)...
// Add the module and its packages.
if (!dupl_modules && dupl_pkg_index == -1) {
if (!dupl_modules && existing_pkg == NULL) {
// Create the entry for this module in the class loader's module entry table.
ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
version_symbol, location_symbol, loader_data);
@ -426,13 +431,10 @@ void Modules::define_module(jobject module, jstring version,
// any errors ?
if (dupl_modules) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
err_msg("Module %s is already defined", module_name));
}
if (dupl_pkg_index != -1) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s for module %s already exists for class loader",
pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
} else if (existing_pkg != NULL) {
throw_dup_pkg_exception(module_name, existing_pkg, CHECK);
}
if (log_is_enabled(Debug, modules)) {
@ -497,8 +499,8 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
}
void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
if (package == NULL) {
void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@ -526,10 +528,9 @@ void Modules::add_module_exports(jobject from_module, jstring package, jobject t
}
}
PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
PackageEntry *package_entry = get_package_entry(from_module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in from_module %s",
package_name != NULL ? package_name : "",
@ -557,7 +558,7 @@ void Modules::add_module_exports(jobject from_module, jstring package, jobject t
}
void Modules::add_module_exports_qualified(jobject from_module, jstring package,
void Modules::add_module_exports_qualified(jobject from_module, const char* package,
jobject to_module, TRAPS) {
if (to_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
@ -649,21 +650,15 @@ jobject Modules::get_module(jclass clazz, TRAPS) {
}
jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
jobject Modules::get_module_by_package_name(jobject loader, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_module_from_pkg before " JAVA_BASE_NAME " is defined");
if (NULL == package) {
if (package_name == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
const char* package_str =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (NULL == package_str) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid package", JNI_FALSE);
}
Handle h_loader (THREAD, JNIHandles::resolve(loader));
// Check that loader is a subclass of java.lang.ClassLoader.
@ -672,7 +667,7 @@ jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRA
"Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE);
}
if (strlen(package_str) == 0) {
if (strlen(package_name) == 0) {
// Return the unnamed module
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
if (NULL == module_table) return NULL;
@ -680,24 +675,24 @@ jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRA
return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
} else {
TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
return get_module(package_sym, h_loader, CHECK_NULL);
}
return NULL;
}
jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) {
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_named_module before " JAVA_BASE_NAME " is defined");
assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
"Class loader is not a subclass of java.lang.ClassLoader");
assert(package_str != NULL, "the package_str should not be NULL");
assert(package_name != NULL, "the package_name should not be NULL");
if (strlen(package_str) == 0) {
if (strlen(package_name) == 0) {
return NULL;
}
TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
const PackageEntry* const pkg_entry =
get_package_entry_by_name(package_sym, h_loader, THREAD);
const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
@ -723,14 +718,14 @@ jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
return NULL;
}
void Modules::add_module_package(jobject module, jstring package, TRAPS) {
void Modules::add_module_package(jobject module, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
if (package == NULL) {
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@ -743,11 +738,6 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module cannot be an unnamed module");
}
char *package_name = java_lang_String::as_utf8_string(
JNIHandles::resolve_non_null(package));
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
}
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s", package_name));
@ -760,12 +750,15 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
!loader_data->is_platform_class_loader_data() &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(loader_data);
StringUtils::replace_no_expand(package_name, "/", ".");
size_t pkg_len = strlen(package_name);
char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
strncpy(pkg_name, package_name, pkg_len);
StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@ -776,31 +769,29 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
PackageEntryTable* package_table = loader_data->packages();
assert(package_table != NULL, "Missing package_table");
bool pkg_exists = false;
PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
// Check that the package does not exist in the class loader's package table.
if (!package_table->lookup_only(pkg_symbol)) {
existing_pkg = package_table->lookup_only(pkg_symbol);
if (existing_pkg == NULL) {
PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
assert(pkg != NULL, "Unable to create a module's package entry");
} else {
pkg_exists = true;
}
}
if (pkg_exists) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s already exists for class loader", package_name));
if (existing_pkg != NULL) {
throw_dup_pkg_exception(module_entry->name()->as_C_string(), existing_pkg, CHECK);
}
}
// Export package in module to all unnamed modules.
void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
if (package == NULL) {
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@ -811,10 +802,9 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package,
}
if (module_entry->is_named()) { // No-op for unnamed module.
PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
PackageEntry *package_entry = get_package_entry(module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in module %s",
package_name != NULL ? package_name : "",
@ -833,10 +823,7 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package,
package_entry->name()->as_C_string(),
module_entry->name()->as_C_string());
// Mark package as exported to all unnamed modules, unless already
// unqualifiedly exported.
if (!package_entry->is_unqual_exported()) {
package_entry->set_is_exported_allUnnamed();
}
// Mark package as exported to all unnamed modules.
package_entry->set_is_exported_allUnnamed();
}
}

View File

@ -48,9 +48,12 @@ public:
// * Packages contains a duplicate package name
// * A package already exists in another module for this class loader
// * Module is an unnamed module
// * num_packages is negative
// * num_packages is non-zero when packages is null
// NullPointerExceptions are thrown if module is null.
static void define_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS);
jstring location, const char* const* packages,
jsize num_packages, TRAPS);
// Provides the java.lang.reflect.Module for the unnamed module defined
// to the boot loader.
@ -72,7 +75,7 @@ public:
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
static void add_module_exports(jobject from_module, const char* package, jobject to_module, TRAPS);
// This does a qualified export of package in module from_module to module
// to_module. The format for the package name must use "/' not ".".
@ -83,7 +86,7 @@ public:
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
static void add_module_exports_qualified(jobject from_module, const char* package, jobject to_module, TRAPS);
// add_reads_module adds module to_module to the list of modules that from_module
// can read. If from_module is the same as to_module then this is a no-op.
@ -102,7 +105,7 @@ public:
// NullPointerException is thrown if package is null.
// IllegalArgumentException is thrown if loader is neither null nor a subtype of
// java/lang/ClassLoader.
static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
static jobject get_module_by_package_name(jobject loader, const char* package, TRAPS);
static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
// If package is defined by loader, return the
@ -116,16 +119,16 @@ public:
// * Module is unnamed
// * Package is not syntactically correct
// * Package is already defined for module's class loader.
static void add_module_package(jobject module, jstring package, TRAPS);
static void add_module_package(jobject module, const char* package, TRAPS);
// Marks the specified package as exported to all unnamed modules.
// If either module or package is null then NullPointerException is thrown.
// If module or package is bad, or module is unnamed, or package is not in
// module then IllegalArgumentException is thrown.
static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
static void add_module_exports_to_all_unnamed(jobject module, const char* package, TRAPS);
// Return TRUE if package_name is syntactically valid, false otherwise.
static bool verify_package_name(char *package_name);
static bool verify_package_name(const char *package_name);
// Return TRUE iff package is defined by loader
static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);

Some files were not shown because too many files have changed in this diff Show More