This commit is contained in:
Serguei Spitsyn 2016-09-09 06:44:31 +00:00
commit 98babf0899
59 changed files with 1462 additions and 243 deletions
hotspot
src
test

@ -2921,6 +2921,26 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
__ cmp( Rold, O7 );
%}
// raw int cas without using tmp register for compareAndExchange
enc_class enc_casi_exch( iRegP mem, iRegL old, iRegL new) %{
Register Rmem = reg_to_register_object($mem$$reg);
Register Rold = reg_to_register_object($old$$reg);
Register Rnew = reg_to_register_object($new$$reg);
MacroAssembler _masm(&cbuf);
__ cas(Rmem, Rold, Rnew);
%}
// 64-bit cas without using tmp register for compareAndExchange
enc_class enc_casx_exch( iRegP mem, iRegL old, iRegL new) %{
Register Rmem = reg_to_register_object($mem$$reg);
Register Rold = reg_to_register_object($old$$reg);
Register Rnew = reg_to_register_object($new$$reg);
MacroAssembler _masm(&cbuf);
__ casx(Rmem, Rold, Rnew);
%}
enc_class enc_lflags_ne_to_boolean( iRegI res ) %{
Register Rres = reg_to_register_object($res$$reg);
@ -7105,6 +7125,7 @@ instruct storeLConditional( iRegP mem_ptr, iRegL oldval, g3RegL newval, flagsReg
instruct compareAndSwapL_bool(iRegP mem_ptr, iRegL oldval, iRegL newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
predicate(VM_Version::supports_cx8());
match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp1);
format %{
"MOV $newval,O7\n\t"
@ -7121,6 +7142,7 @@ instruct compareAndSwapL_bool(iRegP mem_ptr, iRegL oldval, iRegL newval, iRegI r
instruct compareAndSwapI_bool(iRegP mem_ptr, iRegI oldval, iRegI newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp1);
format %{
"MOV $newval,O7\n\t"
@ -7139,6 +7161,7 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r
predicate(VM_Version::supports_cx8());
#endif
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp1);
format %{
"MOV $newval,O7\n\t"
@ -7159,6 +7182,7 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r
instruct compareAndSwapN_bool(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp1);
format %{
"MOV $newval,O7\n\t"
@ -7172,6 +7196,54 @@ instruct compareAndSwapN_bool(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI r
ins_pipe( long_memory_op );
%}
instruct compareAndExchangeI(iRegP mem_ptr, iRegI oldval, iRegI newval)
%{
match(Set newval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
effect( USE mem_ptr );
format %{
"CASA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr] and set $newval=[$mem_ptr]\n\t"
%}
ins_encode( enc_casi_exch(mem_ptr, oldval, newval) );
ins_pipe( long_memory_op );
%}
instruct compareAndExchangeL(iRegP mem_ptr, iRegL oldval, iRegL newval)
%{
match(Set newval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
effect( USE mem_ptr );
format %{
"CASXA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr] and set $newval=[$mem_ptr]\n\t"
%}
ins_encode( enc_casx_exch(mem_ptr, oldval, newval) );
ins_pipe( long_memory_op );
%}
instruct compareAndExchangeP(iRegP mem_ptr, iRegP oldval, iRegP newval)
%{
match(Set newval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
effect( USE mem_ptr );
format %{
"CASXA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr] and set $newval=[$mem_ptr]\n\t"
%}
ins_encode( enc_casx_exch(mem_ptr, oldval, newval) );
ins_pipe( long_memory_op );
%}
instruct compareAndExchangeN(iRegP mem_ptr, iRegN oldval, iRegN newval)
%{
match(Set newval (CompareAndExchangeN mem_ptr (Binary oldval newval)));
effect( USE mem_ptr );
format %{
"CASA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr] and set $newval=[$mem_ptr]\n\t"
%}
ins_encode( enc_casi_exch(mem_ptr, oldval, newval) );
ins_pipe( long_memory_op );
%}
instruct xchgI( memory mem, iRegI newval) %{
match(Set newval (GetAndSetI mem newval));
format %{ "SWAP [$mem],$newval" %}

@ -65,10 +65,10 @@ define_pd_global(intx, InlineSmallCode, 1000);
#ifdef AMD64
// Very large C++ stack frames using solaris-amd64 optimized builds
// due to lack of optimization caused by C++ compiler bugs
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2))
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(7) DEBUG_ONLY(+2))
// For those clients that do not use write socket, we allow
// the min range value to be below that of the default
#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(6) DEBUG_ONLY(+2))
#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(7) DEBUG_ONLY(+2))
#else
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES

@ -8131,8 +8131,7 @@ void MacroAssembler::has_negatives(Register ary1, Register len,
jmp(FALSE_LABEL);
clear_vector_masking(); // closing of the stub context for programming mask registers
}
else {
} else {
movl(result, len); // copy
if (UseAVX == 2 && UseSSE >= 2) {
@ -8169,8 +8168,7 @@ void MacroAssembler::has_negatives(Register ary1, Register len,
bind(COMPARE_TAIL); // len is zero
movl(len, result);
// Fallthru to tail compare
}
else if (UseSSE42Intrinsics) {
} else if (UseSSE42Intrinsics) {
// With SSE4.2, use double quad vector compare
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
@ -10748,7 +10746,10 @@ void MacroAssembler::char_array_compress(Register src, Register dst, Register le
// save length for return
push(len);
// 8165287: EVEX version disabled for now, needs to be refactored as
// it is returning incorrect results.
if ((UseAVX > 2) && // AVX512
0 &&
VM_Version::supports_avx512vlbw() &&
VM_Version::supports_bmi2()) {
@ -11067,10 +11068,11 @@ void MacroAssembler::byte_array_inflate(Register src, Register dst, Register len
bind(below_threshold);
bind(copy_new_tail);
if (UseAVX > 2) {
if ((UseAVX > 2) &&
VM_Version::supports_avx512vlbw() &&
VM_Version::supports_bmi2()) {
movl(tmp2, len);
}
else {
} else {
movl(len, tmp2);
}
andl(tmp2, 0x00000007);

@ -366,8 +366,8 @@ final class CompilerToVM {
* {@code exactReceiver}.
*
* @param caller the caller or context type used to perform access checks
* @return the link-time resolved method (might be abstract) or {@code 0} if it can not be
* linked
* @return the link-time resolved method (might be abstract) or {@code null} if it is either a
* signature polymorphic method or can not be linked.
*/
native HotSpotResolvedJavaMethodImpl resolveMethod(HotSpotResolvedObjectTypeImpl exactReceiver, HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl caller);

@ -722,7 +722,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
/**
* Determines if {@code type} contains signature polymorphic methods.
*/
private static boolean isSignaturePolymorphicHolder(final HotSpotResolvedObjectTypeImpl type) {
static boolean isSignaturePolymorphicHolder(final ResolvedJavaType type) {
String name = type.getName();
if (signaturePolymorphicHolders == null) {
signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders();

@ -24,6 +24,7 @@ package jdk.vm.ci.hotspot;
import static java.util.Objects.requireNonNull;
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
@ -426,7 +427,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
// Methods can only be resolved against concrete types
return null;
}
if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) {
if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic() && !isSignaturePolymorphicHolder(method.getDeclaringClass())) {
return method;
}
if (!method.getDeclaringClass().isAssignableFrom(this)) {

@ -209,8 +209,8 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
*
* @param method the method to select the implementation of
* @param callerType the caller or context type used to perform access checks
* @return the method that would be selected at runtime (might be abstract) or {@code null} if
* it can not be resolved
* @return the link-time resolved method (might be abstract) or {@code null} if it is either a
* signature polymorphic method or can not be linked.
*/
ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType);

@ -2875,7 +2875,7 @@ void os::Linux::rebuild_cpu_to_node_map() {
// in the library.
const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
size_t cpu_num = os::active_processor_count();
size_t cpu_num = processor_count();
size_t cpu_map_size = NCPUS / BitsPerCLong;
size_t cpu_map_valid_size =
MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);

@ -2504,13 +2504,15 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// It write enables the page immediately after protecting it
// so just return.
if (exception_code == EXCEPTION_ACCESS_VIOLATION) {
JavaThread* thread = (JavaThread*) t;
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
address addr = (address) exceptionRecord->ExceptionInformation[1];
if (os::is_memory_serialize_page(thread, addr)) {
// Block current thread until the memory serialize page permission restored.
os::block_on_serialize_page_trap();
return EXCEPTION_CONTINUE_EXECUTION;
if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t;
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
address addr = (address) exceptionRecord->ExceptionInformation[1];
if (os::is_memory_serialize_page(thread, addr)) {
// Block current thread until the memory serialize page permission restored.
os::block_on_serialize_page_trap();
return EXCEPTION_CONTINUE_EXECUTION;
}
}
}
@ -2564,7 +2566,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
#endif
if (thread->stack_guards_enabled()) {
if (_thread_in_Java) {
if (in_java) {
frame fr;
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
address addr = (address) exceptionRecord->ExceptionInformation[1];
@ -2576,6 +2578,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// Yellow zone violation. The o/s has unprotected the first yellow
// zone page for us. Note: must call disable_stack_yellow_zone to
// update the enabled status, even if the zone contains only one page.
assert(thread->thread_state() != _thread_in_vm, "Undersized StackShadowPages");
thread->disable_stack_yellow_reserved_zone();
// If not in java code, return and hope for the best.
return in_java
@ -3793,6 +3796,11 @@ void os::win32::initialize_system_info() {
GlobalMemoryStatusEx(&ms);
_physical_memory = ms.ullTotalPhys;
if (FLAG_IS_DEFAULT(MaxRAM)) {
// Adjust MaxRAM according to the maximum virtual address space available.
FLAG_SET_DEFAULT(MaxRAM, MIN2(MaxRAM, (uint64_t) ms.ullTotalVirtual));
}
OSVERSIONINFOEX oi;
oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO*)&oi);

@ -2410,6 +2410,15 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
#endif // INCLUDE_ALL_GCS
if (x->is_volatile() && os::is_MP()) __ membar_acquire();
/* Normalize boolean value returned by unsafe operation, i.e., value != 0 ? value = true : value false. */
if (type == T_BOOLEAN) {
LabelObj* equalZeroLabel = new LabelObj();
__ cmp(lir_cond_equal, value, 0);
__ branch(lir_cond_equal, T_BOOLEAN, equalZeroLabel->label());
__ move(LIR_OprFact::intConst(1), value);
__ branch_destination(equalZeroLabel->label());
}
}

@ -576,9 +576,8 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// normal bytecode execution.
thread->clear_exception_oop_and_pc();
Handle original_exception(thread, exception());
continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false);
bool recursive_exception = false;
continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false, recursive_exception);
// If an exception was thrown during exception dispatch, the exception oop may have changed
thread->set_exception_oop(exception());
thread->set_exception_pc(pc);
@ -586,8 +585,9 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// the exception cache is used only by non-implicit exceptions
// Update the exception cache only when there didn't happen
// another exception during the computation of the compiled
// exception handler.
if (continuation != NULL && original_exception() == exception()) {
// exception handler. Checking for exception oop equality is not
// sufficient because some exceptions are pre-allocated and reused.
if (continuation != NULL && !recursive_exception) {
nm->add_handler_for_exception_and_pc(exception, pc, continuation);
}
}

@ -5407,6 +5407,59 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
debug_only(ik->verify();)
}
// For an anonymous class that is in the unnamed package, move it to its host class's
// package by prepending its host class's package name to its class name and setting
// its _class_name field.
void ClassFileParser::prepend_host_package_name(const InstanceKlass* host_klass, TRAPS) {
ResourceMark rm(THREAD);
assert(strrchr(_class_name->as_C_string(), '/') == NULL,
"Anonymous class should not be in a package");
const char* host_pkg_name =
ClassLoader::package_from_name(host_klass->name()->as_C_string(), NULL);
if (host_pkg_name != NULL) {
size_t host_pkg_len = strlen(host_pkg_name);
int class_name_len = _class_name->utf8_length();
char* new_anon_name =
NEW_RESOURCE_ARRAY(char, host_pkg_len + 1 + class_name_len);
// Copy host package name and trailing /.
strncpy(new_anon_name, host_pkg_name, host_pkg_len);
new_anon_name[host_pkg_len] = '/';
// Append anonymous class name. The anonymous class name can contain odd
// characters. So, do a strncpy instead of using sprintf("%s...").
strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len);
// Create a symbol and update the anonymous class name.
_class_name = SymbolTable::new_symbol(new_anon_name,
(int)host_pkg_len + 1 + class_name_len,
CHECK);
}
}
// If the host class and the anonymous class are in the same package then do
// nothing. If the anonymous class is in the unnamed package then move it to its
// host's package. If the classes are in different packages then throw an IAE
// exception.
void ClassFileParser::fix_anonymous_class_name(TRAPS) {
assert(_host_klass != NULL, "Expected an anonymous class");
const jbyte* anon_last_slash = UTF8::strrchr(_class_name->base(),
_class_name->utf8_length(), '/');
if (anon_last_slash == NULL) { // Unnamed package
prepend_host_package_name(_host_klass, CHECK);
} else {
if (!InstanceKlass::is_same_class_package(_host_klass->class_loader(),
_host_klass->name(),
_host_klass->class_loader(),
_class_name)) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Host class %s and anonymous class %s are in different packages",
_host_klass->name()->as_C_string(), _class_name->as_C_string()));
}
}
}
static bool relax_format_check_for(ClassLoaderData* loader_data) {
bool trusted = (loader_data->is_the_null_class_loader_data() ||
SystemDictionary::is_platform_class_loader(loader_data->class_loader()));
@ -5422,7 +5475,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
Publicity pub_level,
TRAPS) :
@ -5697,6 +5750,13 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
return;
}
// if this is an anonymous class fix up its name if it's in the unnamed
// package. Otherwise, throw IAE if it is in a different package than
// its host class.
if (_host_klass != NULL) {
fix_anonymous_class_name(CHECK);
}
// Verification prevents us from creating names with dots in them, this
// asserts that that's the case.
assert(is_internal_format(_class_name), "external class name format used internally");

@ -79,7 +79,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
const Symbol* _requested_name;
Symbol* _class_name;
mutable ClassLoaderData* _loader_data;
const Klass* _host_klass;
const InstanceKlass* _host_klass;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
// Metadata created before the instance klass is created. Must be deallocated
@ -155,6 +155,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
ConstantPool* cp,
TRAPS);
void prepend_host_package_name(const InstanceKlass* host_klass, TRAPS);
void fix_anonymous_class_name(TRAPS);
void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS);
void set_klass(InstanceKlass* instance);
@ -474,7 +477,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
Publicity pub_level,
TRAPS);
@ -500,7 +503,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool is_anonymous() const { return _host_klass != NULL; }
bool is_interface() const { return _access_flags.is_interface(); }
const Klass* host_klass() const { return _host_klass; }
const InstanceKlass* host_klass() const { return _host_klass; }
const GrowableArray<Handle>* cp_patches() const { return _cp_patches; }
ClassLoaderData* loader_data() const { return _loader_data; }
const Symbol* class_name() const { return _class_name; }

@ -966,7 +966,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
// Klasses to delete.
bool walk_all_metadata = clean_previous_versions &&
JvmtiExport::has_redefined_a_class() &&
InstanceKlass::has_previous_versions();
InstanceKlass::has_previous_versions_and_reset();
MetadataOnStackMark md_on_stack(walk_all_metadata);
// Save previous _unloading pointer for CMS which may add to unloading list before

@ -94,7 +94,7 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS) {

@ -72,7 +72,7 @@ class KlassFactory : AllStatic {
Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS);
};

@ -1027,7 +1027,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name,
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS) {

@ -299,7 +299,7 @@ public:
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
const Klass* host_klass,
const InstanceKlass* host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS);

@ -2786,7 +2786,7 @@ void ClassVerifier::verify_invoke_instructions(
// direct interface relative to the host class
have_imr_indirect = (have_imr_indirect &&
!is_same_or_direct_interface(
InstanceKlass::cast(current_class()->host_klass()),
current_class()->host_klass(),
host_klass_type, ref_class_type));
}
if (!subtype) {

@ -1305,7 +1305,7 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) {
event.set_entryCount(heap->blob_count());
event.set_methodCount(heap->nmethod_count());
event.set_adaptorCount(heap->adapter_count());
event.set_unallocatedCapacity(heap->unallocated_capacity()/K);
event.set_unallocatedCapacity(heap->unallocated_capacity());
event.set_fullCount(heap->full_count());
event.commit();
}

@ -3511,6 +3511,7 @@ bool CMSCollector::do_marking_mt() {
conc_workers()->active_workers(),
Threads::number_of_non_daemon_threads());
num_workers = conc_workers()->update_active_workers(num_workers);
log_info(gc,task)("Using %u workers of %u for marking", num_workers, conc_workers()->total_workers());
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();

@ -899,6 +899,8 @@ void ParNewGeneration::collect(bool full,
workers->active_workers(),
Threads::number_of_non_daemon_threads());
active_workers = workers->update_active_workers(active_workers);
log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers->total_workers());
_old_gen = gch->old_gen();
// If the next generation is too full to accommodate worst-case promotion

@ -1332,6 +1332,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc,
workers()->active_workers(),
Threads::number_of_non_daemon_threads());
workers()->update_active_workers(n_workers);
log_info(gc,task)("Using %u workers of %u to rebuild remembered set", n_workers, workers()->total_workers());
ParRebuildRSTask rebuild_rs_task(this);
workers()->run_task(&rebuild_rs_task);
@ -3068,6 +3069,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
workers()->active_workers(),
Threads::number_of_non_daemon_threads());
workers()->update_active_workers(active_workers);
log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers());
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());

@ -1035,6 +1035,8 @@ void G1ConcurrentMark::mark_from_roots() {
// worker threads may currently exist and more may not be
// available.
active_workers = _parallel_workers->update_active_workers(active_workers);
log_info(gc, task)("Using %u workers of %u for marking", active_workers, _parallel_workers->total_workers());
// Parallel task terminator is set in "set_concurrency_and_phase()"
set_concurrency_and_phase(active_workers, true /* concurrent */);

@ -162,7 +162,7 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
_active_workers = MIN2(v, _total_workers);
add_workers(false /* exit_on_failure */);
assert(v != 0, "Trying to set active workers to 0");
log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
log_trace(gc, task)("%s: using %d out of %d workers", name(), _active_workers, _total_workers);
return _active_workers;
}

@ -576,27 +576,39 @@ void InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code byt
// compute auxiliary field attributes
TosState state = as_TosState(info.field_type());
// Put instructions on final fields are not resolved. This is required so we throw
// exceptions at the correct place (when the instruction is actually invoked).
// Resolution of put instructions on final fields is delayed. That is required so that
// exceptions are thrown at the correct place (when the instruction is actually invoked).
// If we do not resolve an instruction in the current pass, leaving the put_code
// set to zero will cause the next put instruction to the same field to reresolve.
// Resolution of put instructions to final instance fields with invalid updates (i.e.,
// to final instance fields with updates originating from a method different than <init>)
// is inhibited. A putfield instruction targeting an instance final field must throw
// an IllegalAccessError if the instruction is not in an instance
// initializer method <init>. If resolution were not inhibited, a putfield
// in an initializer method could be resolved in the initializer. Subsequent
// putfield instructions to the same field would then use cached information.
// As a result, those instructions would not pass through the VM. That is,
// checks in resolve_field_access() would not be executed for those instructions
// and the required IllegalAccessError would not be thrown.
//
// Also, we need to delay resolving getstatic and putstatic instructions until the
// class is initialized. This is required so that access to the static
// field will call the initialization function every time until the class
// is completely initialized ala. in 2.17.5 in JVM Specification.
InstanceKlass* klass = InstanceKlass::cast(info.field_holder());
bool uninitialized_static = ((bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic) &&
!klass->is_initialized());
Bytecodes::Code put_code = (Bytecodes::Code)0;
if (is_put && !info.access_flags().is_final() && !uninitialized_static) {
put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
}
bool uninitialized_static = is_static && !klass->is_initialized();
bool has_initialized_final_update = info.field_holder()->major_version() >= 53 &&
info.has_initialized_final_update();
assert(!(has_initialized_final_update && !info.access_flags().is_final()), "Fields with initialized final updates must be final");
Bytecodes::Code get_code = (Bytecodes::Code)0;
Bytecodes::Code put_code = (Bytecodes::Code)0;
if (!uninitialized_static) {
get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield);
if ((is_put && !has_initialized_final_update) || !info.access_flags().is_final()) {
put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
}
}
cp_cache_entry->set_field(

@ -768,6 +768,11 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t
Symbol* h_name = method->name();
Symbol* h_signature = method->signature();
if (MethodHandles::is_signature_polymorphic_method(method())) {
// Signature polymorphic methods are already resolved, JVMCI just returns NULL in this case.
return NULL;
}
LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass);
methodHandle m;
// Only do exact lookup if receiver klass has been linked. Otherwise,
@ -782,7 +787,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t
}
if (m.is_null()) {
// Return NULL only if there was a problem with lookup (uninitialized class, etc.)
// Return NULL if there was a problem with lookup (uninitialized class, etc.)
return NULL;
}

@ -313,13 +313,18 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// normal bytecode execution.
thread->clear_exception_oop_and_pc();
continuation = SharedRuntime::compute_compiled_exc_handler(cm, pc, exception, false, false);
bool recursive_exception = false;
continuation = SharedRuntime::compute_compiled_exc_handler(cm, pc, exception, false, false, recursive_exception);
// If an exception was thrown during exception dispatch, the exception oop may have changed
thread->set_exception_oop(exception());
thread->set_exception_pc(pc);
// the exception cache is used only by non-implicit exceptions
if (continuation != NULL && !SharedRuntime::deopt_blob()->contains(continuation)) {
// Update the exception cache only when there didn't happen
// another exception during the computation of the compiled
// exception handler. Checking for exception oop equality is not
// sufficient because some exceptions are pre-allocated and reused.
if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {
cm->add_handler_for_exception_and_pc(exception, pc, continuation);
}
}

@ -385,6 +385,7 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr,
const char* decoratorstr,
const char* output_options,
outputStream* errstream) {
assert(errstream != NULL, "errstream can not be NULL");
if (outputstr == NULL || strlen(outputstr) == 0) {
outputstr = "stdout";
}

@ -3365,88 +3365,119 @@ void InstanceKlass::set_init_state(ClassState state) {
#if INCLUDE_JVMTI
// RedefineClasses() support for previous versions:
int InstanceKlass::_previous_version_count = 0;
// RedefineClasses() support for previous versions
// Purge previous versions before adding new previous versions of the class.
void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
if (ik->previous_versions() != NULL) {
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
// Globally, there is at least one previous version of a class to walk
// during class unloading, which is saved because old methods in the class
// are still running. Otherwise the previous version list is cleaned up.
bool InstanceKlass::_has_previous_versions = false;
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
ClassLoaderData* loader_data = ik->class_loader_data();
assert(loader_data != NULL, "should never be null");
// Returns true if there are previous versions of a class for class
// unloading only. Also resets the flag to false. purge_previous_version
// will set the flag to true if there are any left, i.e., if there's any
// work to do for next time. This is to avoid the expensive code cache
// walk in CLDG::do_unloading().
bool InstanceKlass::has_previous_versions_and_reset() {
bool ret = _has_previous_versions;
log_trace(redefine, class, iklass, purge)("Class unloading: has_previous_versions = %s",
ret ? "true" : "false");
_has_previous_versions = false;
return ret;
}
ResourceMark rm;
log_trace(redefine, class, iklass, purge)("%s: previous versions", ik->external_name());
// Purge previous versions before adding new previous versions of the class and
// during class unloading.
void InstanceKlass::purge_previous_version_list() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
assert(has_been_redefined(), "Should only be called for main class");
// previous versions are linked together through the InstanceKlass
InstanceKlass* pv_node = ik->previous_versions();
InstanceKlass* last = ik;
int version = 0;
// Quick exit.
if (previous_versions() == NULL) {
return;
}
// check the previous versions list
for (; pv_node != NULL; ) {
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
ConstantPool* pvcp = pv_node->constants();
assert(pvcp != NULL, "cp ref was unexpectedly cleared");
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
ClassLoaderData* loader_data = class_loader_data();
assert(loader_data != NULL, "should never be null");
if (!pvcp->on_stack()) {
// If the constant pool isn't on stack, none of the methods
// are executing. Unlink this previous_version.
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
// so will be deallocated during the next phase of class unloading.
log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is dead", p2i(pv_node));
// For debugging purposes.
pv_node->set_is_scratch_class();
pv_node->class_loader_data()->add_to_deallocate_list(pv_node);
pv_node = pv_node->previous_versions();
last->link_previous_versions(pv_node);
deleted_count++;
version++;
continue;
} else {
log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
}
ResourceMark rm;
log_trace(redefine, class, iklass, purge)("%s: previous versions", external_name());
// At least one method is live in this previous version.
// Reset dead EMCP methods not to get breakpoints.
// All methods are deallocated when all of the methods for this class are no
// longer running.
Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length());
for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
// previous versions are linked together through the InstanceKlass
InstanceKlass* pv_node = previous_versions();
InstanceKlass* last = this;
int version = 0;
if (!method->on_stack()) {
// no breakpoints for non-running methods
if (method->is_running_emcp()) {
method->set_running_emcp(false);
}
} else {
assert (method->is_obsolete() || method->is_running_emcp(),
"emcp method cannot run after emcp bit is cleared");
log_trace(redefine, class, iklass, purge)
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(), method->signature()->as_C_string(), j, version);
// check the previous versions list
for (; pv_node != NULL; ) {
ConstantPool* pvcp = pv_node->constants();
assert(pvcp != NULL, "cp ref was unexpectedly cleared");
if (!pvcp->on_stack()) {
// If the constant pool isn't on stack, none of the methods
// are executing. Unlink this previous_version.
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
// so will be deallocated during the next phase of class unloading.
log_trace(redefine, class, iklass, purge)
("previous version " INTPTR_FORMAT " is dead.", p2i(pv_node));
// For debugging purposes.
pv_node->set_is_scratch_class();
// Unlink from previous version list.
assert(pv_node->class_loader_data() == loader_data, "wrong loader_data");
InstanceKlass* next = pv_node->previous_versions();
pv_node->link_previous_versions(NULL); // point next to NULL
last->link_previous_versions(next);
// Add to the deallocate list after unlinking
loader_data->add_to_deallocate_list(pv_node);
pv_node = next;
deleted_count++;
version++;
continue;
} else {
log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
// found a previous version for next time we do class unloading
_has_previous_versions = true;
}
// At least one method is live in this previous version.
// Reset dead EMCP methods not to get breakpoints.
// All methods are deallocated when all of the methods for this class are no
// longer running.
Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length());
for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
if (!method->on_stack()) {
// no breakpoints for non-running methods
if (method->is_running_emcp()) {
method->set_running_emcp(false);
}
} else {
assert (method->is_obsolete() || method->is_running_emcp(),
"emcp method cannot run after emcp bit is cleared");
log_trace(redefine, class, iklass, purge)
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(), method->signature()->as_C_string(), j, version);
}
}
// next previous version
last = pv_node;
pv_node = pv_node->previous_versions();
version++;
}
log_trace(redefine, class, iklass, purge)
("previous version stats: live=%d, deleted=%d",
live_count, deleted_count);
// next previous version
last = pv_node;
pv_node = pv_node->previous_versions();
version++;
}
log_trace(redefine, class, iklass, purge)
("previous version stats: live=%d, deleted=%d", live_count, deleted_count);
}
void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
@ -3518,8 +3549,8 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
log_trace(redefine, class, iklass, add)
("adding previous version ref for %s, EMCP_cnt=%d", scratch_class->external_name(), emcp_method_count);
// Clean out old previous versions
purge_previous_versions(this);
// Clean out old previous versions for this class
purge_previous_version_list();
// Mark newly obsolete methods in remaining previous versions. An EMCP method from
// a previous redefinition may be made obsolete by this redefinition.
@ -3536,8 +3567,6 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
// For debugging purposes.
scratch_class->set_is_scratch_class();
scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class());
// Update count for class unloading.
_previous_version_count--;
return;
}
@ -3565,12 +3594,12 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
}
// Add previous version if any methods are still running.
log_trace(redefine, class, iklass, add)("scratch class added; one of its methods is on_stack");
// Set has_previous_version flag for processing during class unloading.
_has_previous_versions = true;
log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack.");
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class());
// Update count for class unloading.
_previous_version_count++;
} // end add_previous_version()
#endif // INCLUDE_JVMTI

@ -619,8 +619,8 @@ class InstanceKlass: public Klass {
objArrayOop signers() const;
// host class
Klass* host_klass() const {
Klass** hk = (Klass**)adr_host_klass();
InstanceKlass* host_klass() const {
InstanceKlass** hk = adr_host_klass();
if (hk == NULL) {
return NULL;
} else {
@ -628,9 +628,9 @@ class InstanceKlass: public Klass {
return *hk;
}
}
void set_host_klass(const Klass* host) {
void set_host_klass(const InstanceKlass* host) {
assert(is_anonymous(), "not anonymous");
const Klass** addr = (const Klass**)adr_host_klass();
const InstanceKlass** addr = (const InstanceKlass **)adr_host_klass();
assert(addr != NULL, "no reversed space");
if (addr != NULL) {
*addr = host;
@ -709,6 +709,7 @@ class InstanceKlass: public Klass {
// RedefineClasses() support for previous versions:
void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
void purge_previous_version_list();
InstanceKlass* previous_versions() const { return _previous_versions; }
#else
@ -768,10 +769,15 @@ public:
}
private:
static int _previous_version_count;
static bool _has_previous_versions;
public:
static void purge_previous_versions(InstanceKlass* ik);
static bool has_previous_versions() { return _previous_version_count > 0; }
static void purge_previous_versions(InstanceKlass* ik) {
if (ik->has_been_redefined()) {
ik->purge_previous_version_list();
}
}
static bool has_previous_versions_and_reset();
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
void set_cached_class_file(JvmtiCachedClassFileData *data) {
@ -792,7 +798,7 @@ public:
#else // INCLUDE_JVMTI
static void purge_previous_versions(InstanceKlass* ik) { return; };
static bool has_previous_versions() { return false; }
static bool has_previous_versions_and_reset() { return false; }
void set_cached_class_file(JvmtiCachedClassFileData *data) {
assert(data == NULL, "unexpected call with JVMTI disabled");
@ -1057,13 +1063,13 @@ public:
}
};
Klass** adr_host_klass() const {
InstanceKlass** adr_host_klass() const {
if (is_anonymous()) {
Klass** adr_impl = adr_implementor();
InstanceKlass** adr_impl = (InstanceKlass **)adr_implementor();
if (adr_impl != NULL) {
return adr_impl + 1;
} else {
return end_of_nonstatic_oop_maps();
return (InstanceKlass **)end_of_nonstatic_oop_maps();
}
} else {
return NULL;

@ -431,6 +431,12 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
if (clean_alive_klasses && current->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(current);
ik->clean_weak_instanceklass_links(is_alive);
// JVMTI RedefineClasses creates previous versions that are not in
// the class hierarchy, so process them here.
while ((ik = ik->previous_versions()) != NULL) {
ik->clean_weak_instanceklass_links(is_alive);
}
}
}
}

@ -2172,10 +2172,9 @@ Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) {
java_bc() == Bytecodes::_instanceof ||
java_bc() == Bytecodes::_aastore) {
ciProfileData* data = method()->method_data()->bci_to_data(bci());
bool maybe_null = data == NULL ? true : data->as_BitData()->null_seen();
maybe_null = data == NULL ? true : data->as_BitData()->null_seen();
}
return record_profile_for_speculation(n, exact_kls, maybe_null);
return n;
}
/**

@ -2475,6 +2475,28 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
// load value
switch (type) {
case T_BOOLEAN:
{
// Normalize the value returned by getBoolean in the following cases
if (mismatched ||
heap_base_oop == top() || // - heap_base_oop is NULL or
(can_access_non_heap && alias_type->field() == NULL) // - heap_base_oop is potentially NULL
// and the unsafe access is made to large offset
// (i.e., larger than the maximum offset necessary for any
// field access)
) {
IdealKit ideal = IdealKit(this);
#define __ ideal.
IdealVariable normalized_result(ideal);
__ declarations_done();
__ set(normalized_result, p);
__ if_then(p, BoolTest::ne, ideal.ConI(0));
__ set(normalized_result, ideal.ConI(1));
ideal.end_if();
final_sync(ideal);
p = __ value(normalized_result);
#undef __
}
}
case T_CHAR:
case T_BYTE:
case T_SHORT:

@ -1349,17 +1349,23 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t
force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc);
if (handler_address == NULL) {
Handle original_exception(thread, exception());
handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true);
bool recursive_exception = false;
handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
assert (handler_address != NULL, "must have compiled handler");
// Update the exception cache only when the unwind was not forced
// and there didn't happen another exception during the computation of the
// compiled exception handler.
if (!force_unwind && original_exception() == exception()) {
// compiled exception handler. Checking for exception oop equality is not
// sufficient because some exceptions are pre-allocated and reused.
if (!force_unwind && !recursive_exception) {
nm->add_handler_for_exception_and_pc(exception,pc,handler_address);
}
} else {
assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same");
#ifdef ASSERT
bool recursive_exception = false;
address computed_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
vmassert(recursive_exception || (handler_address == computed_address), "Handler address inconsistency: " PTR_FORMAT " != " PTR_FORMAT,
p2i(handler_address), p2i(computed_address));
#endif
}
}

@ -649,18 +649,14 @@ JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) {
jvmtiError
JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) {
LogLevelType level = value == 0 ? LogLevel::Off : LogLevel::Info;
switch (flag) {
case JVMTI_VERBOSE_OTHER:
// ignore
break;
case JVMTI_VERBOSE_CLASS:
if (value == 0) {
LogConfiguration::parse_log_arguments("stdout", "class+unload=off", NULL, NULL, NULL);
LogConfiguration::parse_log_arguments("stdout", "class+load=off", NULL, NULL, NULL);
} else {
LogConfiguration::parse_log_arguments("stdout", "class+load=info", NULL, NULL, NULL);
LogConfiguration::parse_log_arguments("stdout", "class+unload=info", NULL, NULL, NULL);
}
LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload));
LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, load));
break;
case JVMTI_VERBOSE_GC:
if (value == 0) {

@ -150,14 +150,23 @@ class MemoryAccess : StackObj {
}
template <typename T>
T normalize(T x) {
T normalize_for_write(T x) {
return x;
}
jboolean normalize(jboolean x) {
jboolean normalize_for_write(jboolean x) {
return x & 1;
}
template <typename T>
T normalize_for_read(T x) {
return x;
}
jboolean normalize_for_read(jboolean x) {
return x != 0;
}
/**
* Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
*/
@ -196,7 +205,7 @@ public:
T* p = (T*)addr();
T x = *p;
T x = normalize_for_read(*p);
return x;
}
@ -207,7 +216,7 @@ public:
T* p = (T*)addr();
*p = normalize(x);
*p = normalize_for_write(x);
}
@ -223,7 +232,7 @@ public:
T x = OrderAccess::load_acquire((volatile T*)p);
return x;
return normalize_for_read(x);
}
template <typename T>
@ -232,7 +241,7 @@ public:
T* p = (T*)addr();
OrderAccess::release_store_fence((volatile T*)p, normalize(x));
OrderAccess::release_store_fence((volatile T*)p, normalize_for_write(x));
}
@ -256,7 +265,7 @@ public:
jlong* p = (jlong*)addr();
Atomic::store(normalize(x), p);
Atomic::store(normalize_for_write(x), p);
}
#endif
};
@ -783,6 +792,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na
// define a class but do not make it known to the class loader or system dictionary
// - host_class: supplies context for linkage, access control, protection domain, and class loader
// if host_class is itself anonymous then it is replaced with its host class.
// - data: bytes of a class file, a raw memory address (length gives the number of bytes)
// - cp_patches: where non-null entries exist, they replace corresponding CP entries in data
@ -791,8 +801,12 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na
// link to any member of U. Just after U is loaded, the only way to use it is reflectively,
// through java.lang.Class methods like Class.newInstance.
// The package of an anonymous class must either match its host's class's package or be in the
// unnamed package. If it is in the unnamed package then it will be put in its host class's
// package.
//
// Access checks for linkage sites within U continue to follow the same rules as for named classes.
// The package of an anonymous class is given by the package qualifier on the name under which it was loaded.
// An anonymous class also has special privileges to access any member of its host class.
// This is the main reason why this loading operation is unsafe. The purpose of this is to
// allow language implementations to simulate "open classes"; a host class in effect gets
@ -874,9 +888,11 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
// Primitive types have NULL Klass* fields in their java.lang.Class instances.
if (host_klass == NULL) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Host class is null");
}
assert(host_klass->is_instance_klass(), "Host class must be an instance class");
const char* host_source = host_klass->external_name();
Handle host_loader(THREAD, host_klass->class_loader());
Handle host_domain(THREAD, host_klass->protection_domain());
@ -907,7 +923,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
host_loader,
host_domain,
&st,
host_klass,
InstanceKlass::cast(host_klass),
cp_patches,
CHECK_NULL);
if (anonk == NULL) {

@ -33,8 +33,9 @@
#include "gc/shared/referenceProcessor.hpp"
#include "gc/shared/taskqueue.hpp"
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "logging/logConfiguration.hpp"
#include "logging/logStream.hpp"
#include "logging/logTag.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
@ -4176,7 +4177,10 @@ bool Arguments::handle_deprecated_print_gc_flags() {
if (_gc_log_filename != NULL) {
// -Xloggc was used to specify a filename
const char* gc_conf = PrintGCDetails ? "gc*" : "gc";
return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, NULL);
LogTarget(Error, logging) target;
LogStreamCHeap errstream(target);
return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, &errstream);
} else if (PrintGC || PrintGCDetails) {
LogConfiguration::configure_stdout(LogLevel::Info, !PrintGCDetails, LOG_TAGS(gc));
}

@ -219,6 +219,9 @@ class ThreadInVMfromJava : public ThreadStateTransition {
trans_from_java(_thread_in_vm);
}
~ThreadInVMfromJava() {
if (_thread->stack_yellow_reserved_zone_disabled()) {
_thread->enable_stack_yellow_reserved_zone();
}
trans(_thread_in_vm, _thread_in_Java);
// Check for pending. async. exceptions or suspends.
if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition();
@ -306,6 +309,9 @@ class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition {
trans_from_java(_thread_in_vm);
}
~ThreadInVMfromJavaNoAsyncException() {
if (_thread->stack_yellow_reserved_zone_disabled()) {
_thread->enable_stack_yellow_reserved_zone();
}
trans(_thread_in_vm, _thread_in_Java);
// NOTE: We do not check for pending. async. exceptions.
// If we did and moved the pending async exception over into the
@ -314,6 +320,7 @@ class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition {
// to the _thread_in_vm state. Instead we postpone the handling of
// the async exception.
// Check for pending. suspends only.
if (_thread->has_special_runtime_exit_condition())
_thread->handle_special_runtime_exit_condition(false);

@ -412,13 +412,13 @@ oop Reflection::array_component_type(oop mirror, TRAPS) {
return result;
}
static bool under_host_klass(const InstanceKlass* ik, const Klass* host_klass) {
static bool under_host_klass(const InstanceKlass* ik, const InstanceKlass* host_klass) {
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
for (;;) {
const Klass* hc = (const Klass*)ik->host_klass();
const InstanceKlass* hc = ik->host_klass();
if (hc == NULL) return false;
if (hc == host_klass) return true;
ik = InstanceKlass::cast(hc);
ik = hc;
// There's no way to make a host class loop short of patching memory.
// Therefore there cannot be a loop here unless there's another bug.
@ -436,8 +436,8 @@ static bool can_relax_access_check_for(const Klass* accessor,
// If either is on the other's host_klass chain, access is OK,
// because one is inside the other.
if (under_host_klass(accessor_ik, accessee) ||
under_host_klass(accessee_ik, accessor))
if (under_host_klass(accessor_ik, accessee_ik) ||
under_host_klass(accessee_ik, accessor_ik))
return true;
if ((RelaxAccessControlCheck &&

@ -621,7 +621,7 @@ JRT_END
// ret_pc points into caller; we are returning caller's exception handler
// for given exception
address SharedRuntime::compute_compiled_exc_handler(CompiledMethod* cm, address ret_pc, Handle& exception,
bool force_unwind, bool top_frame_only) {
bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred) {
assert(cm != NULL, "must exist");
ResourceMark rm;
@ -677,6 +677,7 @@ address SharedRuntime::compute_compiled_exc_handler(CompiledMethod* cm, address
// BCI of the exception handler which caused the exception to be
// thrown (bugs 4307310 and 4546590). Set "exception" reference
// argument to ensure that the correct exception is thrown (4870175).
recursive_exception_occurred = true;
exception = Handle(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
if (handler_bci >= 0) {

@ -189,7 +189,7 @@ class SharedRuntime: AllStatic {
// exception handling and implicit exceptions
static address compute_compiled_exc_handler(CompiledMethod* nm, address ret_pc, Handle& exception,
bool force_unwind, bool top_frame_only);
bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred);
enum ImplicitExceptionKind {
IMPLICIT_NULL,
IMPLICIT_DIVIDE_BY_ZERO,

@ -183,11 +183,8 @@ size_t ClassLoadingService::compute_class_size(InstanceKlass* k) {
bool ClassLoadingService::set_verbose(bool verbose) {
MutexLocker m(Management_lock);
// verbose will be set to the previous value
if (verbose) {
LogConfiguration::parse_log_arguments("stdout", "class+load=info", NULL, NULL, NULL);
} else {
LogConfiguration::parse_log_arguments("stdout", "class+load=off", NULL, NULL, NULL);
}
LogLevelType level = verbose ? LogLevel::Info : LogLevel::Off;
LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, load));
reset_trace_class_unloading();
return verbose;
}
@ -196,11 +193,8 @@ bool ClassLoadingService::set_verbose(bool verbose) {
void ClassLoadingService::reset_trace_class_unloading() {
assert(Management_lock->owned_by_self(), "Must own the Management_lock");
bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose();
if (value) {
LogConfiguration::parse_log_arguments("stdout", "class+unload=info", NULL, NULL, NULL);
} else {
LogConfiguration::parse_log_arguments("stdout", "class+unload=off", NULL, NULL, NULL);
}
LogLevelType level = value ? LogLevel::Info : LogLevel::Off;
LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload));
}
GrowableArray<KlassHandle>* LoadedClassesEnumerator::_loaded_classes = NULL;

@ -75,6 +75,7 @@ public class OverflowCodeCacheTest {
System.out.printf("type %s%n", type);
System.out.println("allocating till possible...");
ArrayList<Long> blobs = new ArrayList<>();
int compilationActivityMode = -1;
try {
long addr;
int size = (int) (getHeapSize() >> 7);
@ -88,13 +89,16 @@ public class OverflowCodeCacheTest {
type + " doesn't allow using " + actualType + " when overflow");
}
}
Asserts.assertNotEquals(WHITE_BOX.getCompilationActivityMode(), 1 /* run_compilation*/,
"Compilation must be disabled when CodeCache(CodeHeap) overflows");
/* now, remember compilationActivityMode to check it later, after freeing, since we
possibly have no free cache for futher work */
compilationActivityMode = WHITE_BOX.getCompilationActivityMode();
} finally {
for (Long blob : blobs) {
WHITE_BOX.freeCodeBlob(blob);
}
}
Asserts.assertNotEquals(compilationActivityMode, 1 /* run_compilation*/,
"Compilation must be disabled when CodeCache(CodeHeap) overflows");
}
private long getHeapSize() {

@ -62,7 +62,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
public class CallSiteDepContextTest {
static final Unsafe UNSAFE = Unsafe.getUnsafe();
static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
static final String CLASS_NAME = "java/lang/invoke/Test";
static final String CLASS_NAME = "compiler/jsr292/Test";
static final String METHOD_NAME = "m";
static final MethodType TYPE = MethodType.methodType(int.class);
@ -129,8 +129,8 @@ public class CallSiteDepContextTest {
}
public static void testSharedCallSite() throws Throwable {
Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null);
Class<?> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
Class<?> cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_1"), null);
Class<?> cls2 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_2"), null);
MethodHandle[] mhs = new MethodHandle[] {
LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),
@ -151,7 +151,7 @@ public class CallSiteDepContextTest {
execute(1, mh);
// mcs.context == cls1
Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("NonBound_1"), null);
Class<?> cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("NonBound_1"), null);
MethodHandle mh1 = LOOKUP.findStatic(cls1, METHOD_NAME, TYPE);
execute(1, mh1);
@ -170,8 +170,8 @@ public class CallSiteDepContextTest {
mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
Class<?>[] cls = new Class[] {
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null),
UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null),
UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_1" + id), null),
UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_2" + id), null),
};
MethodHandle[] mhs = new MethodHandle[] {
@ -185,7 +185,7 @@ public class CallSiteDepContextTest {
execute(1, mhs);
ref = new PhantomReference<>(cls[0], rq);
cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null);
cls[0] = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_3" + id), null);
mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
do {

@ -19,7 +19,6 @@ import java.util.List;
* @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
* @library /test/lib /
* @library ../common/patches
* @ignore 8139383
* @modules java.base/jdk.internal.misc
* @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.org.objectweb.asm.tree

@ -25,7 +25,6 @@
* @test
* @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
* @library ../../../../../
* @ignore 8161550
* @modules java.base/jdk.internal.reflect
* jdk.vm.ci/jdk.vm.ci.meta
* jdk.vm.ci/jdk.vm.ci.runtime
@ -74,11 +73,29 @@ import static org.junit.Assert.assertTrue;
/**
* Tests for {@link ResolvedJavaType}.
*/
@SuppressWarnings("unchecked")
public class TestResolvedJavaType extends TypeUniverse {
private static final Class<? extends Annotation> SIGNATURE_POLYMORPHIC_CLASS = findPolymorphicSignatureClass();
public TestResolvedJavaType() {
}
private static Class<? extends Annotation> findPolymorphicSignatureClass() {
Class<? extends Annotation> signaturePolyAnnotation = null;
try {
for (Class<?> clazz : TestResolvedJavaType.class.getClassLoader().loadClass("java.lang.invoke.MethodHandle").getDeclaredClasses()) {
if (clazz.getName().endsWith("PolymorphicSignature") && Annotation.class.isAssignableFrom(clazz)) {
signaturePolyAnnotation = (Class<? extends Annotation>) clazz;
break;
}
}
} catch (Throwable e) {
throw new AssertionError("Could not find annotation PolymorphicSignature in java.lang.invoke.MethodHandle", e);
}
assertNotNull(signaturePolyAnnotation);
return signaturePolyAnnotation;
}
@Test
public void findInstanceFieldWithOffsetTest() {
for (Class<?> c : classes) {
@ -577,8 +594,14 @@ public class TestResolvedJavaType extends TypeUniverse {
for (Method decl : decls) {
ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
if (m.isPublic()) {
ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
assertEquals(m.toString(), i, type.resolveMethod(m, context));
ResolvedJavaMethod resolvedmethod = type.resolveMethod(m, context);
if (isSignaturePolymorphic(m)) {
// Signature polymorphic methods must not be resolved
assertNull(resolvedmethod);
} else {
ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
assertEquals(m.toString(), i, resolvedmethod);
}
}
}
}
@ -606,8 +629,14 @@ public class TestResolvedJavaType extends TypeUniverse {
for (Method decl : decls) {
ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl);
if (m.isPublic()) {
ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
assertEquals(i, type.resolveConcreteMethod(m, context));
ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(m, context);
if (isSignaturePolymorphic(m)) {
// Signature polymorphic methods must not be resolved
assertNull(String.format("Got: %s", resolvedMethod), resolvedMethod);
} else {
ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl);
assertEquals(i, resolvedMethod);
}
}
}
}
@ -929,4 +958,8 @@ public class TestResolvedJavaType extends TypeUniverse {
}
}
}
private static boolean isSignaturePolymorphic(ResolvedJavaMethod method) {
return method.getAnnotation(SIGNATURE_POLYMORPHIC_CLASS) != null;
}
}

@ -22,51 +22,32 @@
*
*/
/**
* @test
* @bug 6869327
* @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @ignore 8146096
* @run driver compiler.loopopts.UseCountedLoopSafepoints
*/
package compiler.loopopts;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.util.concurrent.atomic.AtomicLong;
import java.lang.reflect.Method;
import sun.hotspot.WhiteBox;
import jdk.test.lib.Asserts;
import compiler.whitebox.CompilerWhiteBoxTest;
public class UseCountedLoopSafepoints {
private static final AtomicLong _num = new AtomicLong(0);
private static final WhiteBox WB = WhiteBox.getWhiteBox();
private static final String METHOD_NAME = "testMethod";
private long accum = 0;
// Uses the fact that an EnableBiasedLocking vmop will be started
// after 500ms, while we are still in the loop. If there is a
// safepoint in the counted loop, then we will reach safepoint
// very quickly. Otherwise SafepointTimeout will be hit.
public static void main (String args[]) throws Exception {
if (args.length == 1) {
final int loops = Integer.parseInt(args[0]);
for (int i = 0; i < loops; i++) {
_num.addAndGet(1);
}
} else {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+IgnoreUnrecognizedVMOptions",
"-XX:-TieredCompilation",
"-XX:+UseBiasedLocking",
"-XX:BiasedLockingStartupDelay=500",
"-XX:+SafepointTimeout",
"-XX:SafepointTimeoutDelay=2000",
"-XX:+UseCountedLoopSafepoints",
UseCountedLoopSafepoints.class.getName(),
"2000000000"
);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Timeout detected");
output.shouldHaveExitValue(0);
new UseCountedLoopSafepoints().testMethod();
Method m = UseCountedLoopSafepoints.class.getDeclaredMethod(METHOD_NAME);
String directive = "[{ match: \"" + UseCountedLoopSafepoints.class.getName().replace('.', '/')
+ "." + METHOD_NAME + "\", " + "BackgroundCompilation: false }]";
Asserts.assertTrue(WB.addCompilerDirective(directive) == 1, "Can't add compiler directive");
Asserts.assertTrue(WB.enqueueMethodForCompilation(m,
CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION), "Can't enqueue method");
}
private void testMethod() {
for (int i = 0; i < 100; i++) {
accum += accum << 5 + accum >> 4 - accum >>> 5;
}
}
}

@ -0,0 +1,123 @@
/*
* 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.
*
*/
/**
* @test
* @bug 6869327
* @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
* @library /test/lib /
* @requires vm.compMode != "Xint" & vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
* @modules java.base/jdk.internal.misc
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run driver compiler.loopopts.UseCountedLoopSafepointsTest
*/
package compiler.loopopts;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import jdk.test.lib.Asserts;
/* Idea of this test is to check if ideal graph has CountedLoopEnd->SafePoint edge in case
of UseCountedLoopSafepoint enabled and has no such edge in case it's disabled. Restricting
compilation to testMethod only will leave only one counted loop (the one in testedMethod) */
public class UseCountedLoopSafepointsTest {
public static void main (String args[]) {
check(true); // check ideal graph with UseCountedLoopSafepoint enabled
check(false); // ... and disabled
}
private static void check(boolean enabled) {
OutputAnalyzer oa;
try {
oa = ProcessTools.executeTestJvm("-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.",
"-XX:" + (enabled ? "+" : "-") + "UseCountedLoopSafepoints", "-XX:+WhiteBoxAPI",
"-XX:-Inline", "-Xbatch", "-XX:+PrintIdeal", "-XX:LoopUnrollLimit=0",
"-XX:CompileOnly=" + UseCountedLoopSafepoints.class.getName() + "::testMethod",
UseCountedLoopSafepoints.class.getName());
} catch (Exception e) {
throw new Error("Exception launching child for case enabled=" + enabled + " : " + e, e);
}
oa.shouldHaveExitValue(0);
// parse output in seach of SafePoint and CountedLoopEnd nodes
List<Node> safePoints = new ArrayList<>();
List<Node> loopEnds = new ArrayList<>();
for (String line : oa.getOutput().split("\\n")) {
int separatorIndex = line.indexOf("\t===");
if (separatorIndex > -1) {
String header = line.substring(0, separatorIndex);
if (header.endsWith("\tSafePoint")) {
safePoints.add(new Node("SafePoint", line));
} else if (header.endsWith("\tCountedLoopEnd")) {
loopEnds.add(new Node("CountedLoopEnd", line));
}
}
}
// now, find CountedLoopEnd -> SafePoint edge
boolean found = false;
for (Node loopEnd : loopEnds) {
found |= loopEnd.to.stream()
.filter(id -> nodeListHasElementWithId(safePoints, id))
.findAny()
.isPresent();
}
Asserts.assertEQ(enabled, found, "Safepoint " + (found ? "" : "not ") + "found");
}
private static boolean nodeListHasElementWithId(List<Node> list, int id) {
return list.stream()
.filter(node -> node.id == id)
.findAny()
.isPresent();
}
private static class Node {
public final int id;
public final List<Integer> from;
public final List<Integer> to;
public Node(String name, String str) {
List<Integer> tmpFrom = new ArrayList<>();
List<Integer> tmpTo = new ArrayList<>();
// parse string like: " $id $name === $to1 $to2 ... [[ $from1 $from2 ... ]] $anything"
// example: 318 SafePoint === 317 1 304 1 1 10 308 [[ 97 74 ]] ...
id = Integer.parseInt(str.substring(1, str.indexOf(name)).trim());
Arrays.stream(str.substring(str.indexOf("===") + 4, str.indexOf("[[")).trim().split("\\s+"))
.map(Integer::parseInt)
.forEach(tmpTo::add);
Arrays.stream(str.substring(str.indexOf("[[") + 3, str.indexOf("]]")).trim().split("\\s+"))
.map(Integer::parseInt)
.forEach(tmpFrom::add);
this.from = Collections.unmodifiableList(tmpFrom);
this.to = Collections.unmodifiableList(tmpTo);
}
}
}

@ -0,0 +1,92 @@
/*
* 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.
*/
/*
* @test
* @bug 8161720
* @modules java.base/jdk.internal.misc
* @run main/othervm -Xint UnsafeOffHeapBooleanTest 1
* @run main/othervm -XX:+TieredCompilation -XX:TieredStopAtLevel=3 -Xbatch UnsafeOffHeapBooleanTest 20000
* @run main/othervm -XX:-TieredCompilation -Xbatch UnsafeOffHeapBooleanTest 20000
*/
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
public class UnsafeOffHeapBooleanTest {
static boolean bool0 = false, bool1 = false, result = false;
static Unsafe UNSAFE = Unsafe.getUnsafe();
static long offHeapMemory;
public static void test() {
// Write two bytes to the off-heap memory location, both
// bytes correspond to the boolean value 'true'.
UNSAFE.putShort(null, offHeapMemory, (short)0x0204);
// Read two bytes from the storage allocated above (as booleans).
bool0 = UNSAFE.getBoolean(null, offHeapMemory + 0);
bool1 = UNSAFE.getBoolean(null, offHeapMemory + 1);
result = bool0 & bool1;
}
public static void main(String args[]) {
System.out.println("### Test started");
if (args.length != 1) {
throw new RuntimeException("### Test failure: test called with incorrect number of arguments");
}
// Allocate two bytes of storage.
offHeapMemory = UNSAFE.allocateMemory(2);
try {
for (int i = 0; i < Integer.parseInt(args[0]); i++) {
test();
}
// Check if the two 'true' boolean values were normalized
// (i.e., reduced from the range 1...255 to 1).
if (!bool0 || !bool1 || !result) {
System.out.println("Some of the results below are wrong");
System.out.println("bool0 is: " + bool0);
System.out.println("bool1 is: " + bool1);
System.out.println("bool0 & bool1 is: " + result);
System.out.println("===================================");
throw new RuntimeException("### Test failed");
} else {
System.out.println("Test generated correct results");
System.out.println("bool0 is: " + bool0);
System.out.println("bool1 is: " + bool1);
System.out.println("bool0 & bool1 is: " + result);
System.out.println("===================================");
}
} catch (NumberFormatException e) {
throw new RuntimeException("### Test failure: test called with incorrectly formatted parameter");
}
UNSAFE.freeMemory(offHeapMemory);
System.out.println("### Test passed");
}
}

@ -0,0 +1,95 @@
/*
* 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.
*/
/*
* @test
* @bug 8161720
* @modules java.base/jdk.internal.misc
* @run main/othervm -Xint UnsafeOnHeapBooleanTest 1
* @run main/othervm -XX:-UseOnStackReplacement -XX:+TieredCompilation -XX:TieredStopAtLevel=3 -Xbatch UnsafeOnHeapBooleanTest 20000
* @run main/othervm -XX:-UseOnStackReplacement -XX:-TieredCompilation -Xbatch UnsafeOnHeapBooleanTest 20000
*/
import java.lang.reflect.Field;
import jdk.internal.misc.Unsafe;
public class UnsafeOnHeapBooleanTest {
static short static_v;
static boolean bool0 = false, bool1 = false, result = false;
static Unsafe UNSAFE = Unsafe.getUnsafe();
public static void test() {
try {
// Write two bytes into the static field
// UnsafeOnHeapBooleanTest.static_v write two values. Both
// bytes correspond to the boolean value 'true'.
Field staticVField = UnsafeOnHeapBooleanTest.class.getDeclaredField("static_v");
Object base = UNSAFE.staticFieldBase(staticVField);
long offset = UNSAFE.staticFieldOffset(staticVField);
UNSAFE.putShort(base, offset, (short)0x0204);
// Read two bytes from the static field
// UnsafeOnHeapBooleanTest.static_v (as booleans).
bool0 = UNSAFE.getBoolean(base, offset + 0);
bool1 = UNSAFE.getBoolean(base, offset + 1);
result = bool0 & bool1;
} catch (NoSuchFieldException e) {
throw new RuntimeException("### Test failure: static field UnsafeOnHeapBooleanTest.static_v was not found");
}
}
public static void main(String args[]) {
System.out.println("### Test started");
if (args.length != 1) {
throw new RuntimeException("### Test failure: test called with incorrect number of arguments");
}
try {
for (int i = 0; i < Integer.parseInt(args[0]); i++) {
test();
}
// Check if the two 'true' boolean values were normalized
// (i.e., reduced from the range 1...255 to 1).
if (!bool0 || !bool1 || !result) {
System.out.println("Some of the results below are wrong");
System.out.println("bool0 is: " + bool0);
System.out.println("bool1 is: " + bool1);
System.out.println("bool0 & bool1 is: " + result);
System.out.println("===================================");
throw new RuntimeException("### Test failed");
} else {
System.out.println("Test generated correct results");
System.out.println("bool0 is: " + bool0);
System.out.println("bool1 is: " + bool1);
System.out.println("bool0 & bool1 is: " + result);
System.out.println("===================================");
}
} catch (NumberFormatException e) {
throw new RuntimeException("### Test failure: test called with incorrectly formatted parameter");
}
System.out.println("### Test passed");
}
}

@ -0,0 +1,85 @@
/*
* 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.
*/
/*
* @test
* @bug 8161720
* @modules java.base/jdk.internal.misc
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:-TieredCompilation UnsafeSmallOffsetBooleanAccessTest
* @run main/othervm -Xbatch UnsafeSmallOffsetBooleanAccessTest
*/
import java.util.Random;
import jdk.internal.misc.Unsafe;
public class UnsafeSmallOffsetBooleanAccessTest {
static final Unsafe UNSAFE = Unsafe.getUnsafe();
static final long F_OFFSET;
static final Random random = new Random();
static {
try {
F_OFFSET = UNSAFE.objectFieldOffset(T.class.getDeclaredField("f"));
System.out.println("The offset is: " + F_OFFSET);
} catch (Exception e) {
throw new Error(e);
}
}
static class T {
boolean f;
}
// Always return false in a way that is not obvious to the compiler.
public static boolean myRandom() {
if (random.nextInt(101) > 134) {
return true;
} else {
return false;
}
}
public static boolean test(T t) {
boolean result = false;
for (int i = 0; i < 20000; i++) {
boolean random = myRandom();
// If myRandom() returns false, access t.f.
//
// If myRandom() returns true, access virtual address
// F_OFFSET. That address is most likely not mapped,
// therefore the access will most likely cause a
// crash. We're not concerned about that, though, because
// myRandom() always returns false. However, the C2
// compiler avoids normalization of the value returned by
// getBoolean in this case.
result = UNSAFE.getBoolean(myRandom() ? null : t, F_OFFSET);
}
return result;
}
public static void main(String[] args) {
T t = new T();
UNSAFE.putBoolean(t, F_OFFSET, true);
System.out.println("The result for t is: " + test(t));
}
}

@ -0,0 +1,103 @@
/*
* 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.
*/
/*
* @test TestNumWorkerOutput
* @bug 8165292
* @summary Check that when PrintGCDetails is enabled, gc,task output is printed only once per collection.
* @key gc
* @requires vm.gc=="null"
* @modules java.base/jdk.internal.misc
* @library /test/lib
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UseConcMarkSweepGC TestNumWorkerOutput UseConcMarkSweepGC
* @run main/othervm -XX:+UseG1GC TestNumWorkerOutput UseG1GC
*/
import sun.hotspot.WhiteBox;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import static jdk.test.lib.Asserts.*;
public class TestNumWorkerOutput {
public static void checkPatternOnce(String pattern, String what) throws Exception {
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(what);
if (!m.find()) {
throw new RuntimeException("Could not find pattern " + pattern + " in output");
}
if (m.find()) {
throw new RuntimeException("Could find pattern " + pattern + " in output more than once");
}
}
public static void runTest(String gcArg) throws Exception {
final String[] arguments = {
"-Xbootclasspath/a:.",
"-XX:+UnlockExperimentalVMOptions",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:+" + gcArg,
"-Xmx10M",
"-XX:+PrintGCDetails",
GCTest.class.getName()
};
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
System.out.println(output.getStdout());
String stdout = output.getStdout();
checkPatternOnce(".*[info.*].*[gc,task.*].*GC\\(0\\) .*Using \\d+ workers of \\d+ for evacuation.*", stdout);
}
public static void main(String[] args) throws Exception {
runTest(args[0]);
}
static class GCTest {
private static final WhiteBox WB = WhiteBox.getWhiteBox();
public static Object holder;
public static void main(String [] args) {
holder = new byte[100];
WB.youngGC();
System.out.println(holder);
}
}
}

@ -0,0 +1,120 @@
/*
* 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.
*/
/*
* @test
* @bug 8165246
* @summary Test has_previous_versions flag and processing during class unloading.
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules java.compiler
* java.instrument
* jdk.jartool/sun.tools.jar
* @run main RedefineClassHelper
* @run main/othervm RedefinePreviousVersions test
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
public class RedefinePreviousVersions {
public static String newB =
"class RedefinePreviousVersions$B {" +
"}";
static class B { }
public static String newRunning =
"class RedefinePreviousVersions$Running {" +
" public static volatile boolean stop = true;" +
" static void localSleep() { }" +
" public static void infinite() { }" +
"}";
static class Running {
public static volatile boolean stop = false;
static void localSleep() {
try{
Thread.currentThread().sleep(10);//sleep for 10 ms
} catch(InterruptedException ie) {
}
}
public static void infinite() {
while (!stop) { localSleep(); }
}
}
public static void main(String[] args) throws Exception {
if (args.length > 0) {
String jarFile = System.getProperty("test.src") + "/testcase.jar";
// java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
"-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
"RedefinePreviousVersions");
new OutputAnalyzer(pb.start())
.shouldContain("Class unloading: has_previous_versions = false")
.shouldContain("Class unloading: has_previous_versions = true")
.shouldHaveExitValue(0);
return;
}
// Redefine a class and create some garbage
// Since there are no methods running, the previous version is never added to the
// previous_version_list and the flag _has_previous_versions should stay false
RedefineClassHelper.redefineClass(B.class, newB);
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
System.gc();
}
// Start a class that has a method running
new Thread() {
public void run() {
Running.infinite();
}
}.start();
// Since a method of newRunning is running, this class should be added to the previous_version_list
// of Running, and _has_previous_versions should return true at class unloading.
RedefineClassHelper.redefineClass(Running.class, newRunning);
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
System.gc();
}
// purge should clean everything up, except Xcomp it might not.
Running.stop = true;
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
System.gc();
}
}
}

@ -0,0 +1,134 @@
/*
* 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.
*/
/*
* @test DefineAnon
* @bug 8058575
* @library /testlibrary
* @modules java.base/jdk.internal.org.objectweb.asm
* java.management
* @compile -XDignore.symbol.file=true DefineAnon.java
* @run main/othervm p1.DefineAnon
*/
package p1;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import sun.misc.Unsafe;
class T {
static protected void test0() { System.out.println("test0 (public)"); }
static protected void test1() { System.out.println("test1 (protected)"); }
static /*package-private*/ void test2() { System.out.println("test2 (package)"); }
static private void test3() { System.out.println("test3 (private)"); }
}
public class DefineAnon {
private static Unsafe getUnsafe() {
try {
java.lang.reflect.Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
singleoneInstanceField.setAccessible(true);
return (Unsafe) singleoneInstanceField.get(null);
} catch (Throwable ex) {
throw new RuntimeException("Was unable to get Unsafe instance.");
}
}
static Unsafe UNSAFE = DefineAnon.getUnsafe();
static Class<?> getAnonClass(Class<?> hostClass, final String className) {
final String superName = "java/lang/Object";
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, "test", "()V", null, null);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test0", "()V", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test1", "()V", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test2", "()V", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test3", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
final byte[] classBytes = cw.toByteArray();
Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, classBytes, new Object[0]);
UNSAFE.ensureClassInitialized(invokerClass);
return invokerClass;
}
public static void main(String[] args) throws Throwable {
Throwable fail = null;
// Anonymous class has the privileges of its host class, so test[0123] should all work.
System.out.println("Injecting from the same package (p1):");
Class<?> p1cls = getAnonClass(T.class, "p1/AnonClass");
try {
p1cls.getMethod("test").invoke(null);
} catch (Throwable ex) {
ex.printStackTrace();
fail = ex; // throw this to make test fail, since subtest failed
}
// Anonymous class has different package name from host class. Should throw
// IllegalArgumentException.
System.out.println("Injecting from the wrong package (p2):");
try {
Class<?> p2cls = getAnonClass(DefineAnon.class, "p2/AnonClass");
p2cls.getMethod("test").invoke(null);
System.out.println("Failed, did not get expected IllegalArgumentException");
} catch (java.lang.IllegalArgumentException e) {
if (e.getMessage().contains("Host class p1/DefineAnon and anonymous class p2/AnonClass")) {
System.out.println("Got expected IllegalArgumentException: " + e.getMessage());
} else {
throw new RuntimeException("Unexpected message: " + e.getMessage());
}
} catch (Throwable ex) {
ex.printStackTrace();
fail = ex; // throw this to make test fail, since subtest failed
}
// Inject a class in the unnamed package into p1.T. It should be able
// to access all methods in p1.T.
System.out.println("Injecting unnamed package into correct host class:");
try {
Class<?> p3cls = getAnonClass(T.class, "AnonClass");
p3cls.getMethod("test").invoke(null);
} catch (Throwable ex) {
ex.printStackTrace();
fail = ex; // throw this to make test fail, since subtest failed
}
// Try using an array class as the host class. This should throw IllegalArgumentException.
try {
Class<?> p3cls = getAnonClass(String[].class, "AnonClass");
throw new RuntimeException("Expected IllegalArgumentException not thrown");
} catch (IllegalArgumentException ex) {
}
if (fail != null) throw fail; // make test fail, since subtest failed
}
}

@ -0,0 +1,91 @@
/*
* 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.
*/
/*
* @test
* @bug 8058575
* @summary Creates an anonymous class inside of an anonymous class.
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
* @run main p.NestedUnsafe
*/
package p;
import java.security.ProtectionDomain;
import java.io.InputStream;
import java.lang.*;
import jdk.test.lib.*;
import jdk.internal.misc.Unsafe;
import jdk.test.lib.unsafe.UnsafeHelper;
// Test that an anonymous class in package 'p' cannot define its own anonymous class
// in another package.
public class NestedUnsafe {
// The String concatenation should create the nested anonymous class.
static byte klassbuf[] = InMemoryJavaCompiler.compile("q.TestClass",
"package q; " +
"public class TestClass { " +
" public static void concat(String one, String two) throws Throwable { " +
" System.out.println(one + two);" +
" } } ");
public static void main(String args[]) throws Exception {
Unsafe unsafe = UnsafeHelper.getUnsafe();
// The anonymous class calls defineAnonymousClass creating a nested anonymous class.
byte klassbuf2[] = InMemoryJavaCompiler.compile("p.TestClass2",
"package p; " +
"import jdk.internal.misc.Unsafe; " +
"public class TestClass2 { " +
" public static void doit() throws Throwable { " +
" Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " +
" Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, p.NestedUnsafe.klassbuf, new Object[0]); " +
" unsafe.ensureClassInitialized(klass2); " +
" Class[] dArgs = new Class[2]; " +
" dArgs[0] = String.class; " +
" dArgs[1] = String.class; " +
" try { " +
" klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " +
" } catch (Throwable ex) { " +
" throw new RuntimeException(\"Exception: \" + ex.toString()); " +
" } " +
"} } ",
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED");
Class klass2 = unsafe.defineAnonymousClass(p.NestedUnsafe.class, klassbuf2, new Object[0]);
try {
klass2.getMethod("doit").invoke(null);
throw new RuntimeException("Expected exception not thrown");
} catch (Throwable ex) {
Throwable iae = ex.getCause();
if (!iae.toString().contains(
"IllegalArgumentException: Host class p/NestedUnsafe and anonymous class q/TestClass")) {
throw new RuntimeException("Exception: " + iae.toString());
}
}
}
}

@ -0,0 +1,90 @@
/*
* 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.
*/
/*
* @test
* @bug 8058575
* @summary Creates an anonymous class inside of an anonymous class.
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
* @run main p.NestedUnsafe2
*/
package p;
import java.security.ProtectionDomain;
import java.io.InputStream;
import java.lang.*;
import jdk.test.lib.*;
import jdk.internal.misc.Unsafe;
import jdk.test.lib.unsafe.UnsafeHelper;
// Test that an anonymous class that gets put in its host's package cannot define
// an anonymous class in another package.
public class NestedUnsafe2 {
// The String concatenation should create the nested anonymous class.
public static byte klassbuf[] = InMemoryJavaCompiler.compile("q.TestClass",
"package q; " +
"public class TestClass { " +
" public static void concat(String one, String two) throws Throwable { " +
" System.out.println(one + two);" +
" } } ");
public static void main(String args[]) throws Exception {
Unsafe unsafe = UnsafeHelper.getUnsafe();
// The anonymous class calls defineAnonymousClass creating a nested anonymous class.
byte klassbuf2[] = InMemoryJavaCompiler.compile("TestClass2",
"import jdk.internal.misc.Unsafe; " +
"public class TestClass2 { " +
" public static void doit() throws Throwable { " +
" Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " +
" Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, p.NestedUnsafe2.klassbuf, new Object[0]); " +
" unsafe.ensureClassInitialized(klass2); " +
" Class[] dArgs = new Class[2]; " +
" dArgs[0] = String.class; " +
" dArgs[1] = String.class; " +
" try { " +
" klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " +
" } catch (Throwable ex) { " +
" throw new RuntimeException(\"Exception: \" + ex.toString()); " +
" } " +
"} } ",
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED");
Class klass2 = unsafe.defineAnonymousClass(p.NestedUnsafe2.class, klassbuf2, new Object[0]);
try {
klass2.getMethod("doit").invoke(null);
throw new RuntimeException("Expected exception not thrown");
} catch (Throwable ex) {
Throwable iae = ex.getCause();
if (!iae.toString().contains(
"IllegalArgumentException: Host class p/NestedUnsafe2 and anonymous class q/TestClass")) {
throw new RuntimeException("Exception: " + iae.toString());
}
}
}
}

@ -40,7 +40,7 @@ TESTLIBRARY_DIR = ../../../../test/lib
JAVAC = $(JDK_HOME)/bin/javac
JAR = $(JDK_HOME)/bin/jar
SRC_FILES = $(shell find $(SRC_DIR) $(TESTLIBRARY_DIR)/share/classes -name '*.java')
SRC_FILES = $(shell find $(SRC_DIR) $(TESTLIBRARY_DIR)/jdk/test/lib -name '*.java')
WB_SRC_FILES = $(shell find $(TESTLIBRARY_DIR)/sun/hotspot -name '*.java')
MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld

@ -56,7 +56,6 @@ BUILD_DIR = build
CLASSES_DIR = $(BUILD_DIR)/classes
SRC_DIR = src
TEST_DIR = test
DRIVER_DIR = $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg
MANIFEST = manifest.mf
APPLICATION_ARGS += \
--property-file $(PROPERTY_FILE) \
@ -118,19 +117,18 @@ cleantmp:
@rm filelist
@rm -rf $(CLASSES_DIR)
copytestlibrary: $(DRIVER_DIR)
@cp -r src/jdk/test/lib/jittester/jtreg/*.java $(DRIVER_DIR)
copytestlibrary: $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg
@cp -r src/jdk/test/lib/jittester/jtreg/*.java $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg
@cp -r $(TESTLIBRARY_SRC_DIR) $(TESTBASE_DIR)/jdk/test/
testgroup: $(TESTBASE_DIR)
@echo 'jittester_all = \\' > $(TESTGROUP_FILE)
@echo ' /' >> $(TESTGROUP_FILE)
@echo '' >> $(TESTGROUP_FILE)
@echo 'main = \\' >> $(TESTGROUP_FILE)
@echo ' Test_0.java' >> $(TESTGROUP_FILE)
testroot: $(TESTBASE_DIR)
@echo 'groups=TEST.groups' > $(TESTROOT_FILE)
$(TESTBASE_DIR) $(DIST_DIR) $(DRIVER_DIR):
$(TESTBASE_DIR) $(DIST_DIR) $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg:
$(shell if [ ! -d $@ ]; then mkdir -p $@; fi)