# HG changeset patch # User ehelin # Date 1398240754 -7200 # Node ID e378f2bfaaba4716f3629b4cf8305dc011890e95 # Parent dfc2242fc6b084a1ad9d8b97f9686174d0aa39a1# Parent cc0ee6fd0e9769285c08ad5e7ecbfc443c0bc261 Merge diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/make/jprt.properties --- a/hotspot/make/jprt.properties Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/make/jprt.properties Wed Apr 23 10:12:34 2014 +0200 @@ -65,9 +65,6 @@ jprt.my.linux.ppcv2.jdk9=linux_ppcv2_2.6 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}} -jprt.my.linux.ppcsflt.jdk9=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}} - jprt.my.linux.armvfpsflt.jdk9=linux_armvfpsflt_2.6 jprt.my.linux.armvfpsflt=${jprt.my.linux.armvfpsflt.${jprt.tools.default.release}} @@ -113,7 +110,6 @@ ${jprt.my.linux.i586}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppc}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppcv2}-{productEmb|fastdebugEmb}, \ - ${jprt.my.linux.ppcsflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armvfpsflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armvfphflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armsflt}-{productEmb|fastdebugEmb} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -2947,17 +2947,60 @@ istate->_last_Java_fp = last_Java_fp; } -int AbstractInterpreter::layout_activation(Method* method, - int temps, // Number of slots on java expression stack in use. - int popframe_args, - int monitors, // Number of active monitors. - int caller_actual_parameters, - int callee_params,// Number of slots for callee parameters. - int callee_locals,// Number of slots for locals. - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { +// Computes monitor_size and top_frame_size in bytes. +static void frame_size_helper(int max_stack, + int monitors, + int& monitor_size, + int& top_frame_size) { + monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors; + top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() + + monitor_size + + max_stack * Interpreter::stackElementSize + + 2 * Interpreter::stackElementSize, + frame::alignment_in_bytes) + + frame::top_ijava_frame_abi_size; +} + +// Returns number of stackElementWords needed for the interpreter frame with the +// given sections. +int AbstractInterpreter::size_activation(int max_stack, + int temps, + int extra_args, + int monitors, + int callee_params, + int callee_locals, + bool is_top_frame) { + int monitor_size = 0; + int top_frame_size = 0; + frame_size_helper(max_stack, monitors, monitor_size, top_frame_size); + + int frame_size; + if (is_top_frame) { + frame_size = top_frame_size; + } else { + frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() + + monitor_size + + (temps - callee_params + callee_locals) * Interpreter::stackElementSize + + 2 * Interpreter::stackElementSize, + frame::alignment_in_bytes) + + frame::parent_ijava_frame_abi_size; + assert(extra_args == 0, "non-zero for top_frame only"); + } + + return frame_size / Interpreter::stackElementSize; +} + +void AbstractInterpreter::layout_activation(Method* method, + int temps, // Number of slots on java expression stack in use. + int popframe_args, + int monitors, // Number of active monitors. + int caller_actual_parameters, + int callee_params,// Number of slots for callee parameters. + int callee_locals,// Number of slots for locals. + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { // NOTE this code must exactly mimic what // InterpreterGenerator::generate_compute_interpreter_state() does @@ -2967,86 +3010,64 @@ // both the abi scratch area and a place to hold a result from a // callee on its way to the callers stack. - int monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors; - int frame_size; - int top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() - + monitor_size - + (method->max_stack() *Interpreter::stackElementWords * BytesPerWord) - + 2*BytesPerWord, - frame::alignment_in_bytes) - + frame::top_ijava_frame_abi_size; - if (is_top_frame) { - frame_size = top_frame_size; + int monitor_size = 0; + int top_frame_size = 0; + frame_size_helper(method->max_stack(), monitors, monitor_size, top_frame_size); + + intptr_t sp = (intptr_t)interpreter_frame->sp(); + intptr_t fp = *(intptr_t *)sp; + assert(fp == (intptr_t)caller->sp(), "fp must match"); + interpreterState cur_state = + (interpreterState)(fp - frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + + // Now fill in the interpreterState object. + + intptr_t* locals; + if (caller->is_interpreted_frame()) { + // Locals must agree with the caller because it will be used to set the + // caller's tos when we return. + interpreterState prev = caller->get_interpreterState(); + // Calculate start of "locals" for MH calls. For MH calls, the + // current method() (= MH target) and prev->callee() (= + // MH.invoke*()) are different and especially have different + // signatures. To pop the argumentsof the caller, we must use + // the prev->callee()->size_of_arguments() because that's what + // the caller actually pushed. Currently, for synthetic MH + // calls (deoptimized from inlined MH calls), detected by + // is_method_handle_invoke(), we use the callee's arguments + // because here, the caller's and callee's signature match. + if (true /*!caller->is_at_mh_callsite()*/) { + locals = prev->stack() + method->size_of_parameters(); + } else { + // Normal MH call. + locals = prev->stack() + prev->callee()->size_of_parameters(); + } } else { - frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() - + monitor_size - + ((temps - callee_params + callee_locals) * - Interpreter::stackElementWords * BytesPerWord) - + 2*BytesPerWord, - frame::alignment_in_bytes) - + frame::parent_ijava_frame_abi_size; - assert(popframe_args==0, "non-zero for top_frame only"); + bool is_deopted; + locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) + + frame::parent_ijava_frame_abi_size); } - // If we actually have a frame to layout we must now fill in all the pieces. - if (interpreter_frame != NULL) { - - intptr_t sp = (intptr_t)interpreter_frame->sp(); - intptr_t fp = *(intptr_t *)sp; - assert(fp == (intptr_t)caller->sp(), "fp must match"); - interpreterState cur_state = - (interpreterState)(fp - frame::interpreter_frame_cinterpreterstate_size_in_bytes()); - - // Now fill in the interpreterState object. - - intptr_t* locals; - if (caller->is_interpreted_frame()) { - // Locals must agree with the caller because it will be used to set the - // caller's tos when we return. - interpreterState prev = caller->get_interpreterState(); - // Calculate start of "locals" for MH calls. For MH calls, the - // current method() (= MH target) and prev->callee() (= - // MH.invoke*()) are different and especially have different - // signatures. To pop the argumentsof the caller, we must use - // the prev->callee()->size_of_arguments() because that's what - // the caller actually pushed. Currently, for synthetic MH - // calls (deoptimized from inlined MH calls), detected by - // is_method_handle_invoke(), we use the callee's arguments - // because here, the caller's and callee's signature match. - if (true /*!caller->is_at_mh_callsite()*/) { - locals = prev->stack() + method->size_of_parameters(); - } else { - // Normal MH call. - locals = prev->stack() + prev->callee()->size_of_parameters(); - } - } else { - bool is_deopted; - locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) + - frame::parent_ijava_frame_abi_size); - } - - intptr_t* monitor_base = (intptr_t*) cur_state; - intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); - - // Provide pop_frame capability on PPC64, add popframe_args. - // +1 because stack is always prepushed. - intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (temps + popframe_args + 1) * BytesPerWord); - - BytecodeInterpreter::layout_interpreterState(cur_state, - caller, - interpreter_frame, - method, - locals, - stack, - stack_base, - monitor_base, - (intptr_t*)(((intptr_t)fp)-top_frame_size), - is_top_frame); - - BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, - interpreter_frame->fp()); - } - return frame_size/BytesPerWord; + intptr_t* monitor_base = (intptr_t*) cur_state; + intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); + + // Provide pop_frame capability on PPC64, add popframe_args. + // +1 because stack is always prepushed. + intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (temps + popframe_args + 1) * BytesPerWord); + + BytecodeInterpreter::layout_interpreterState(cur_state, + caller, + interpreter_frame, + method, + locals, + stack, + stack_base, + monitor_base, + (intptr_t*)(((intptr_t)fp) - top_frame_size), + is_top_frame); + + BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, + interpreter_frame->fp()); } #endif // CC_INTERP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Wed Apr 23 10:12:34 2014 +0200 @@ -1,6 +1,6 @@ // -// Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -// Copyright 2012, 2013 SAP AG. All rights reserved. +// Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +// Copyright 2012, 2014 SAP AG. 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 @@ -1362,8 +1362,8 @@ Compile* C = ra_->C; MacroAssembler _masm(&cbuf); - const long framesize = ((long)C->frame_slots()) << LogBytesPerInt; - assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); + const long framesize = C->frame_size_in_bytes(); + assert(framesize % (2 * wordSize) == 0, "must preserve 2*wordSize alignment"); const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; @@ -1388,19 +1388,22 @@ // careful, because some VM calls (such as call site linkage) can // use several kilobytes of stack. But the stack safety zone should // account for that. See bugs 4446381, 4468289, 4497237. - if (C->need_stack_bang(framesize) && UseStackBanging) { + + int bangsize = C->bang_size_in_bytes(); + assert(bangsize >= framesize || bangsize <= 0, "stack bang size incorrect"); + if (C->need_stack_bang(bangsize) && UseStackBanging) { // Unfortunately we cannot use the function provided in // assembler.cpp as we have to emulate the pipes. So I had to // insert the code of generate_stack_overflow_check(), see // assembler.cpp for some illuminative comments. const int page_size = os::vm_page_size(); - int bang_end = StackShadowPages*page_size; + int bang_end = StackShadowPages * page_size; // This is how far the previous frame's stack banging extended. const int bang_end_safe = bang_end; - if (framesize > page_size) { - bang_end += framesize; + if (bangsize > page_size) { + bang_end += bangsize; } int bang_offset = bang_end_safe; @@ -1446,7 +1449,7 @@ unsigned int bytes = (unsigned int)framesize; long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes); - ciMethod *currMethod = C -> method(); + ciMethod *currMethod = C->method(); // Optimized version for most common case. if (UsePower6SchedulerPPC64 && diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1334,21 +1334,42 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) { const int max_alignment_size = 2; const int abi_scratch = frame::abi_reg_args_size; - return method->max_locals() + method->max_stack() + frame::interpreter_frame_monitor_size() + max_alignment_size + abi_scratch; + return method->max_locals() + method->max_stack() + + frame::interpreter_frame_monitor_size() + max_alignment_size + abi_scratch; } -// Fills a sceletal interpreter frame generated during deoptimizations -// and returns the frame size in slots. +// Returns number of stackElementWords needed for the interpreter frame with the +// given sections. +// This overestimates the stack by one slot in case of alignments. +int AbstractInterpreter::size_activation(int max_stack, + int temps, + int extra_args, + int monitors, + int callee_params, + int callee_locals, + bool is_top_frame) { + // Note: This calculation must exactly parallel the frame setup + // in AbstractInterpreterGenerator::generate_method_entry. + assert(Interpreter::stackElementWords == 1, "sanity"); + const int max_alignment_space = StackAlignmentInBytes / Interpreter::stackElementSize; + const int abi_scratch = is_top_frame ? (frame::abi_reg_args_size / Interpreter::stackElementSize) : + (frame::abi_minframe_size / Interpreter::stackElementSize); + const int size = + max_stack + + (callee_locals - callee_params) + + monitors * frame::interpreter_frame_monitor_size() + + max_alignment_space + + abi_scratch + + frame::ijava_state_size / Interpreter::stackElementSize; + + // Fixed size of an interpreter frame, align to 16-byte. + return (size & -2); +} + +// Fills a sceletal interpreter frame generated during deoptimizations. // // Parameters: // -// interpreter_frame == NULL: -// Only calculate the size of an interpreter activation, no actual layout. -// Note: This calculation must exactly parallel the frame setup -// in TemplateInterpreter::generate_normal_entry. But it does not -// account for the SP alignment, that might further enhance the -// frame size, depending on FP. -// // interpreter_frame != NULL: // set up the method, locals, and monitors. // The frame interpreter_frame, if not NULL, is guaranteed to be the @@ -1365,59 +1386,41 @@ // the arguments off advance the esp by dummy popframe_extra_args slots. // Popping off those will establish the stack layout as it was before the call. // -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_locals, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_locals_count, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { - const int max_alignment_space = 2; const int abi_scratch = is_top_frame ? (frame::abi_reg_args_size / Interpreter::stackElementSize) : - (frame::abi_minframe_size / Interpreter::stackElementSize) ; - const int conservative_framesize_in_slots = - method->max_stack() + callee_locals - callee_param_count + - (moncount * frame::interpreter_frame_monitor_size()) + max_alignment_space + - abi_scratch + frame::ijava_state_size / Interpreter::stackElementSize; - - assert(!is_top_frame || conservative_framesize_in_slots * 8 > frame::abi_reg_args_size + frame::ijava_state_size, "frame too small"); + (frame::abi_minframe_size / Interpreter::stackElementSize); - if (interpreter_frame == NULL) { - // Since we don't know the exact alignment, we return the conservative size. - return (conservative_framesize_in_slots & -2); - } else { - // Now we know our caller, calc the exact frame layout and size. - intptr_t* locals_base = (caller->is_interpreted_frame()) ? - caller->interpreter_frame_esp() + caller_actual_parameters : - caller->sp() + method->max_locals() - 1 + (frame::abi_minframe_size / Interpreter::stackElementSize) ; + intptr_t* locals_base = (caller->is_interpreted_frame()) ? + caller->interpreter_frame_esp() + caller_actual_parameters : + caller->sp() + method->max_locals() - 1 + (frame::abi_minframe_size / Interpreter::stackElementSize) ; - intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize ; - intptr_t* monitor = monitor_base - (moncount * frame::interpreter_frame_monitor_size()); - intptr_t* esp_base = monitor - 1; - intptr_t* esp = esp_base - tempcount - popframe_extra_args; - intptr_t* sp = (intptr_t *) (((intptr_t) (esp_base- callee_locals + callee_param_count - method->max_stack()- abi_scratch)) & -StackAlignmentInBytes); - intptr_t* sender_sp = caller->sp() + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; - intptr_t* top_frame_sp = is_top_frame ? sp : sp + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; + intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize ; + intptr_t* monitor = monitor_base - (moncount * frame::interpreter_frame_monitor_size()); + intptr_t* esp_base = monitor - 1; + intptr_t* esp = esp_base - tempcount - popframe_extra_args; + intptr_t* sp = (intptr_t *) (((intptr_t) (esp_base - callee_locals_count + callee_param_count - method->max_stack()- abi_scratch)) & -StackAlignmentInBytes); + intptr_t* sender_sp = caller->sp() + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; + intptr_t* top_frame_sp = is_top_frame ? sp : sp + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; - interpreter_frame->interpreter_frame_set_method(method); - interpreter_frame->interpreter_frame_set_locals(locals_base); - interpreter_frame->interpreter_frame_set_cpcache(method->constants()->cache()); - interpreter_frame->interpreter_frame_set_esp(esp); - interpreter_frame->interpreter_frame_set_monitor_end((BasicObjectLock *)monitor); - interpreter_frame->interpreter_frame_set_top_frame_sp(top_frame_sp); - if (!is_bottom_frame) { - interpreter_frame->interpreter_frame_set_sender_sp(sender_sp); - } - - int framesize_in_slots = caller->sp() - sp; - assert(!is_top_frame ||framesize_in_slots >= (frame::abi_reg_args_size / Interpreter::stackElementSize) + frame::ijava_state_size / Interpreter::stackElementSize, "frame too small"); - assert(framesize_in_slots <= conservative_framesize_in_slots, "exact frame size must be smaller than the convervative size!"); - return framesize_in_slots; + interpreter_frame->interpreter_frame_set_method(method); + interpreter_frame->interpreter_frame_set_locals(locals_base); + interpreter_frame->interpreter_frame_set_cpcache(method->constants()->cache()); + interpreter_frame->interpreter_frame_set_esp(esp); + interpreter_frame->interpreter_frame_set_monitor_end((BasicObjectLock *)monitor); + interpreter_frame->interpreter_frame_set_top_frame_sp(top_frame_sp); + if (!is_bottom_frame) { + interpreter_frame->interpreter_frame_set_sender_sp(sender_sp); } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/assembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -630,11 +630,20 @@ } protected: + // Insert a nop if the previous is cbcond + void insert_nop_after_cbcond() { + if (UseCBCond && cbcond_before()) { + nop(); + } + } // Delay slot helpers // cti is called when emitting control-transfer instruction, // BEFORE doing the emitting. // Only effective when assertion-checking is enabled. void cti() { + // A cbcond instruction immediately followed by a CTI + // instruction introduces pipeline stalls, we need to avoid that. + no_cbcond_before(); #ifdef CHECK_DELAY assert_not_delayed("cti should not be in delay slot"); #endif @@ -658,7 +667,6 @@ void no_cbcond_before() { assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond"); } - public: bool use_cbcond(Label& L) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -54,33 +54,33 @@ inline void Assembler::add(Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); } +inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } +inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { insert_nop_after_cbcond(); bpr( c, a, p, s1, target(L)); } -inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::fb( Condition c, bool a, Label& L ) { fb(c, a, target(L)); } +inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } +inline void Assembler::fb( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); fb(c, a, target(L)); } -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { fbp(c, a, cc, p, target(L)); } +inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } +inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); fbp(c, a, cc, p, target(L)); } -inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::br( Condition c, bool a, Label& L ) { br(c, a, target(L)); } +inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } +inline void Assembler::br( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); br(c, a, target(L)); } -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { bp(c, a, cc, p, target(L)); } +inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } +inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); bp(c, a, cc, p, target(L)); } // compare and branch inline void Assembler::cbcond(Condition c, CC cc, Register s1, Register s2, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | rs2(s2)); } inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | immed(true) | simm(simm5, 5)); } -inline void Assembler::call( address d, relocInfo::relocType rt ) { cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } -inline void Assembler::call( Label& L, relocInfo::relocType rt ) { call( target(L), rt); } +inline void Assembler::call( address d, relocInfo::relocType rt ) { insert_nop_after_cbcond(); cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } +inline void Assembler::call( Label& L, relocInfo::relocType rt ) { insert_nop_after_cbcond(); call( target(L), rt); } inline void Assembler::flush( Register s1, Register s2) { emit_int32( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); } inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::jmpl( Register s1, Register s2, Register d ) { cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } -inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } +inline void Assembler::jmpl( Register s1, Register s2, Register d ) { insert_nop_after_cbcond(); cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } +inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { insert_nop_after_cbcond(); cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -152,7 +152,7 @@ } -int LIR_Assembler::initial_frame_size_in_bytes() { +int LIR_Assembler::initial_frame_size_in_bytes() const { return in_bytes(frame_map()->framesize_in_bytes()); } @@ -182,7 +182,7 @@ int number_of_locks = entry_state->locks_size(); // Create a frame for the compiled activation. - __ build_frame(initial_frame_size_in_bytes()); + __ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); // OSR buffer is // diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -55,9 +55,9 @@ } -void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { - - generate_stack_overflow_check(frame_size_in_bytes); +void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { + assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect"); + generate_stack_overflow_check(bang_size_in_bytes); // Create the frame. save_frame_c1(frame_size_in_bytes); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2099,7 +2099,7 @@ int monitor_size = method->is_synchronized() ? 1*frame::interpreter_frame_monitor_size() : 0; return size_activation_helper(method->max_locals(), method->max_stack(), - monitor_size) + call_stub_size; + monitor_size) + call_stub_size; } void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill, @@ -2183,31 +2183,31 @@ istate->_last_Java_pc = (intptr_t*) last_Java_pc; } - -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, // Number of slots on java expression stack in use - int popframe_extra_args, - int moncount, // Number of active monitors - int caller_actual_parameters, - int callee_param_size, - int callee_locals_size, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { +static int frame_size_helper(int max_stack, + int moncount, + int callee_param_size, + int callee_locals_size, + bool is_top_frame, + int& monitor_size, + int& full_frame_words) { + int extra_locals_size = callee_locals_size - callee_param_size; + monitor_size = (sizeof(BasicObjectLock) * moncount) / wordSize; + full_frame_words = size_activation_helper(extra_locals_size, max_stack, monitor_size); + int short_frame_words = size_activation_helper(extra_locals_size, max_stack, monitor_size); + int frame_words = is_top_frame ? full_frame_words : short_frame_words; - assert(popframe_extra_args == 0, "NEED TO FIX"); - // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() - // does as far as allocating an interpreter frame. - // If interpreter_frame!=NULL, set up the method, locals, and monitors. - // The frame interpreter_frame, if not NULL, is guaranteed to be the right size, - // as determined by a previous call to this method. - // It is also guaranteed to be walkable even though it is in a skeletal state + return frame_words; +} + +int AbstractInterpreter::size_activation(int max_stack, + int tempcount, + int extra_args, + int moncount, + int callee_param_size, + int callee_locals_size, + bool is_top_frame) { + assert(extra_args == 0, "NEED TO FIX"); // NOTE: return size is in words not bytes - // NOTE: tempcount is the current size of the java expression stack. For top most - // frames we will allocate a full sized expression stack and not the curback - // version that non-top frames have. - // Calculate the amount our frame will be adjust by the callee. For top frame // this is zero. @@ -2216,87 +2216,108 @@ // to it. So it ignores last_frame_adjust value. Seems suspicious as far // as getting sender_sp correct. - int extra_locals_size = callee_locals_size - callee_param_size; - int monitor_size = (sizeof(BasicObjectLock) * moncount) / wordSize; - int full_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size); - int short_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size); - int frame_words = is_top_frame ? full_frame_words : short_frame_words; + int unused_monitor_size = 0; + int unused_full_frame_words = 0; + return frame_size_helper(max_stack, moncount, callee_param_size, callee_locals_size, is_top_frame, + unused_monitor_size, unused_full_frame_words); +} +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, // Number of slots on java expression stack in use + int popframe_extra_args, + int moncount, // Number of active monitors + int caller_actual_parameters, + int callee_param_size, + int callee_locals_size, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + assert(popframe_extra_args == 0, "NEED TO FIX"); + // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() + // does as far as allocating an interpreter frame. + // Set up the method, locals, and monitors. + // The frame interpreter_frame is guaranteed to be the right size, + // as determined by a previous call to the size_activation() method. + // It is also guaranteed to be walkable even though it is in a skeletal state + // NOTE: tempcount is the current size of the java expression stack. For top most + // frames we will allocate a full sized expression stack and not the curback + // version that non-top frames have. + int monitor_size = 0; + int full_frame_words = 0; + int frame_words = frame_size_helper(method->max_stack(), moncount, callee_param_size, callee_locals_size, + is_top_frame, monitor_size, full_frame_words); /* - if we actually have a frame to layout we must now fill in all the pieces. This means both + We must now fill in all the pieces of the frame. This means both the interpreterState and the registers. */ - if (interpreter_frame != NULL) { - // MUCHO HACK + // MUCHO HACK - intptr_t* frame_bottom = interpreter_frame->sp() - (full_frame_words - frame_words); - // 'interpreter_frame->sp()' is unbiased while 'frame_bottom' must be a biased value in 64bit mode. - assert(((intptr_t)frame_bottom & 0xf) == 0, "SP biased in layout_activation"); - frame_bottom = (intptr_t*)((intptr_t)frame_bottom - STACK_BIAS); + intptr_t* frame_bottom = interpreter_frame->sp() - (full_frame_words - frame_words); + // 'interpreter_frame->sp()' is unbiased while 'frame_bottom' must be a biased value in 64bit mode. + assert(((intptr_t)frame_bottom & 0xf) == 0, "SP biased in layout_activation"); + frame_bottom = (intptr_t*)((intptr_t)frame_bottom - STACK_BIAS); - /* Now fillin the interpreterState object */ + /* Now fillin the interpreterState object */ - interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter)); + interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter)); - intptr_t* locals; + intptr_t* locals; + + // Calculate the postion of locals[0]. This is painful because of + // stack alignment (same as ia64). The problem is that we can + // not compute the location of locals from fp(). fp() will account + // for the extra locals but it also accounts for aligning the stack + // and we can't determine if the locals[0] was misaligned but max_locals + // was enough to have the + // calculate postion of locals. fp already accounts for extra locals. + // +2 for the static long no_params() issue. - // Calculate the postion of locals[0]. This is painful because of - // stack alignment (same as ia64). The problem is that we can - // not compute the location of locals from fp(). fp() will account - // for the extra locals but it also accounts for aligning the stack - // and we can't determine if the locals[0] was misaligned but max_locals - // was enough to have the - // calculate postion of locals. fp already accounts for extra locals. - // +2 for the static long no_params() issue. + if (caller->is_interpreted_frame()) { + // locals must agree with the caller because it will be used to set the + // caller's tos when we return. + interpreterState prev = caller->get_interpreterState(); + // stack() is prepushed. + locals = prev->stack() + method->size_of_parameters(); + } else { + // Lay out locals block in the caller adjacent to the register window save area. + // + // Compiled frames do not allocate a varargs area which is why this if + // statement is needed. + // + intptr_t* fp = interpreter_frame->fp(); + int local_words = method->max_locals() * Interpreter::stackElementWords; - if (caller->is_interpreted_frame()) { - // locals must agree with the caller because it will be used to set the - // caller's tos when we return. - interpreterState prev = caller->get_interpreterState(); - // stack() is prepushed. - locals = prev->stack() + method->size_of_parameters(); + if (caller->is_compiled_frame()) { + locals = fp + frame::register_save_words + local_words - 1; } else { - // Lay out locals block in the caller adjacent to the register window save area. - // - // Compiled frames do not allocate a varargs area which is why this if - // statement is needed. - // - intptr_t* fp = interpreter_frame->fp(); - int local_words = method->max_locals() * Interpreter::stackElementWords; + locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1; + } - if (caller->is_compiled_frame()) { - locals = fp + frame::register_save_words + local_words - 1; - } else { - locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1; - } + } + // END MUCHO HACK - } - // END MUCHO HACK - - intptr_t* monitor_base = (intptr_t*) cur_state; - intptr_t* stack_base = monitor_base - monitor_size; - /* +1 because stack is always prepushed */ - intptr_t* stack = stack_base - (tempcount + 1); + intptr_t* monitor_base = (intptr_t*) cur_state; + intptr_t* stack_base = monitor_base - monitor_size; + /* +1 because stack is always prepushed */ + intptr_t* stack = stack_base - (tempcount + 1); - BytecodeInterpreter::layout_interpreterState(cur_state, - caller, - interpreter_frame, - method, - locals, - stack, - stack_base, - monitor_base, - frame_bottom, - is_top_frame); + BytecodeInterpreter::layout_interpreterState(cur_state, + caller, + interpreter_frame, + method, + locals, + stack, + stack_base, + monitor_base, + frame_bottom, + is_top_frame); - BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp()); - - } - return frame_words; + BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp()); } #endif // CC_INTERP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -3531,7 +3531,7 @@ // was post-decremented.) Skip this address by starting at i=1, and // touch a few more pages below. N.B. It is important to touch all // the way down to and including i=StackShadowPages. - for (int i = 1; i <= StackShadowPages; i++) { + for (int i = 1; i < StackShadowPages; i++) { set((-i*offset)+STACK_BIAS, Rscratch); st(G0, Rtsp, Rscratch); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -233,6 +233,7 @@ } inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); br(c, a, p, target(L)); } @@ -248,6 +249,7 @@ } inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); brx(c, a, p, target(L)); } @@ -269,6 +271,7 @@ } inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); fb(c, a, p, target(L)); } @@ -318,6 +321,7 @@ } inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { + insert_nop_after_cbcond(); MacroAssembler::call( target(L), rt); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -3355,13 +3355,16 @@ Register O4array_size = O4; Label loop; - // Before we make new frames, check to see if stack is available. - // Do this after the caller's return address is on top of stack +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. if (UseStackBanging) { // Get total frame size for interpreted frames __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes(), O4); __ bang_stack_size(O4, O3, G3_scratch); } +#endif __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), O4array_size); __ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), G3pcs); @@ -3409,9 +3412,11 @@ ResourceMark rm; // setup code generation tools int pad = VerifyThread ? 512 : 0;// Extra slop space for more verify code +#ifdef ASSERT if (UseStackBanging) { pad += StackShadowPages*16 + 32; } +#endif #ifdef _LP64 CodeBuffer buffer("deopt_blob", 2100+pad, 512); #else @@ -3632,9 +3637,11 @@ ResourceMark rm; // setup code generation tools int pad = VerifyThread ? 512 : 0; +#ifdef ASSERT if (UseStackBanging) { pad += StackShadowPages*16 + 32; } +#endif #ifdef _LP64 CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512); #else diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Apr 23 10:12:34 2014 +0200 @@ -1193,15 +1193,16 @@ st->print_cr("Verify_Thread"); st->print("\t"); } - size_t framesize = C->frame_slots() << LogBytesPerInt; + size_t framesize = C->frame_size_in_bytes(); + int bangsize = C->bang_size_in_bytes(); // Calls to C2R adapters often do not accept exceptional returns. // We require that their callers must bang for them. But be careful, because // some VM calls (such as call site linkage) can use several kilobytes of // stack. But the stack safety zone should account for that. // See bugs 4446381, 4468289, 4497237. - if (C->need_stack_bang(framesize)) { - st->print_cr("! stack bang"); st->print("\t"); + if (C->need_stack_bang(bangsize)) { + st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); } if (Assembler::is_simm13(-framesize)) { @@ -1225,17 +1226,18 @@ __ verify_thread(); - size_t framesize = C->frame_slots() << LogBytesPerInt; + size_t framesize = C->frame_size_in_bytes(); assert(framesize >= 16*wordSize, "must have room for reg. save area"); assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); + int bangsize = C->bang_size_in_bytes(); // Calls to C2R adapters often do not accept exceptional returns. // We require that their callers must bang for them. But be careful, because // some VM calls (such as call site linkage) can use several kilobytes of // stack. But the stack safety zone should account for that. // See bugs 4446381, 4468289, 4497237. - if (C->need_stack_bang(framesize)) { - __ generate_stack_overflow_check(framesize); + if (C->need_stack_bang(bangsize)) { + __ generate_stack_overflow_check(bangsize); } if (Assembler::is_simm13(-framesize)) { @@ -1268,7 +1270,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { Compile* C = ra_->C; - if( do_polling() && ra_->C->is_method_compilation() ) { + if(do_polling() && ra_->C->is_method_compilation()) { st->print("SETHI #PollAddr,L0\t! Load Polling address\n\t"); #ifdef _LP64 st->print("LDX [L0],G0\t!Poll for Safepointing\n\t"); @@ -1277,8 +1279,12 @@ #endif } - if( do_polling() ) + if(do_polling()) { + if (UseCBCond && !ra_->C->is_method_compilation()) { + st->print("NOP\n\t"); + } st->print("RET\n\t"); + } st->print("RESTORE"); } @@ -1291,15 +1297,20 @@ __ verify_thread(); // If this does safepoint polling, then do it here - if( do_polling() && ra_->C->is_method_compilation() ) { + if(do_polling() && ra_->C->is_method_compilation()) { AddressLiteral polling_page(os::get_polling_page()); __ sethi(polling_page, L0); __ relocate(relocInfo::poll_return_type); - __ ld_ptr( L0, 0, G0 ); + __ ld_ptr(L0, 0, G0); } // If this is a return, then stuff the restore in the delay slot - if( do_polling() ) { + if(do_polling()) { + if (UseCBCond && !ra_->C->is_method_compilation()) { + // Insert extra padding for the case when the epilogue is preceded by + // a cbcond jump, which can't be followed by a CTI instruction + __ nop(); + } __ ret(); __ delayed()->restore(); } else { @@ -2538,7 +2549,7 @@ enc_class call_epilog %{ if( VerifyStackAtCalls ) { MacroAssembler _masm(&cbuf); - int framesize = ra_->C->frame_slots() << LogBytesPerInt; + int framesize = ra_->C->frame_size_in_bytes(); Register temp_reg = G3; __ add(SP, framesize, temp_reg); __ cmp(temp_reg, FP); @@ -3330,7 +3341,18 @@ //----------Instruction Attributes--------------------------------------------- ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute ins_attrib ins_size(32); // Required size attribute (in bits) -ins_attrib ins_avoid_back_to_back(0); // instruction should not be generated back to back + +// avoid_back_to_back attribute is an expression that must return +// one of the following values defined in MachNode: +// AVOID_NONE - instruction can be placed anywhere +// AVOID_BEFORE - instruction cannot be placed after an +// instruction with MachNode::AVOID_AFTER +// AVOID_AFTER - the next instruction cannot be the one +// with MachNode::AVOID_BEFORE +// AVOID_BEFORE_AND_AFTER - BEFORE and AFTER attributes at +// the same time +ins_attrib ins_avoid_back_to_back(MachNode::AVOID_NONE); + ins_attrib ins_short_branch(0); // Required flag: is this instruction a // non-matching short branch variant of some // long branch? @@ -6630,6 +6652,7 @@ ins_encode %{ __ encode_heap_oop($src$$Register, $dst$$Register); %} + ins_avoid_back_to_back(Universe::narrow_oop_base() == NULL ? AVOID_NONE : AVOID_BEFORE); ins_pipe(ialu_reg); %} @@ -9199,6 +9222,7 @@ __ ba(*L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br); %} @@ -9217,7 +9241,7 @@ __ ba_short(*L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9231,6 +9255,7 @@ format %{ "BP$cmp $icc,$labl" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9242,6 +9267,7 @@ format %{ "BP$cmp $icc,$labl" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9260,6 +9286,7 @@ __ bp( (Assembler::Condition)($cmp$$cmpcode), false, Assembler::ptr_cc, predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9278,6 +9305,7 @@ __ fbp( (Assembler::Condition)($cmp$$cmpcode), false, (Assembler::CC)($fcc$$reg), predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_fcc); %} @@ -9290,6 +9318,7 @@ format %{ "BP$cmp $icc,$labl\t! Loop end" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9302,6 +9331,7 @@ format %{ "BP$cmp $icc,$labl\t! Loop end" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9552,7 +9582,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9570,7 +9600,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9588,7 +9618,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9606,7 +9636,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9624,7 +9654,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9642,7 +9672,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9665,7 +9695,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9687,7 +9717,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, G0, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9705,7 +9735,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9723,7 +9753,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, G0, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9742,7 +9772,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9760,7 +9790,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9777,6 +9807,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9789,6 +9820,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9801,6 +9833,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9841,6 +9874,7 @@ __ bp( (Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9968,6 +10002,7 @@ ins_cost(CALL_COST); format %{ "CALL,static ; NOP ==> " %} ins_encode( Java_Static_Call( meth ), call_epilog ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10004,6 +10039,7 @@ format %{ "CALL,runtime" %} ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10016,6 +10052,7 @@ ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10028,6 +10065,7 @@ ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10041,6 +10079,7 @@ ins_cost(CALL_COST); format %{ "Jmp $jump_target ; NOP \t! $method_oop holds method oop" %} ins_encode(form_jmpl(jump_target)); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10072,6 +10111,7 @@ // opcode(Assembler::jmpl_op3, Assembler::arith_op); // The hack duplicates the exception oop into G3, so that CreateEx can use it there. // ins_encode( form3_rs1_simm13_rd( jump_target, 0x00, R_G0 ), move_return_pc_to_o1() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10102,6 +10142,7 @@ // use the following format syntax format %{ "Jmp rethrow_stub" %} ins_encode(enc_rethrow); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10130,6 +10171,7 @@ ins_cost(DEFAULT_COST*10); format %{ "CALL PartialSubtypeCheck\n\tNOP" %} ins_encode( enc_PartialSubtypeCheck() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(partial_subtype_check_pipe); %} @@ -10139,6 +10181,7 @@ ins_cost(DEFAULT_COST*10); format %{ "CALL PartialSubtypeCheck\n\tNOP\t# (sets condition codes)" %} ins_encode( enc_PartialSubtypeCheck() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(partial_subtype_check_pipe); %} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1564,37 +1564,23 @@ int monitor_size = method->is_synchronized() ? 1*frame::interpreter_frame_monitor_size() : 0; return size_activation_helper(method->max_locals(), method->max_stack(), - monitor_size) + call_stub_size; + monitor_size) + call_stub_size; } -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_local_count, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { +int AbstractInterpreter::size_activation(int max_stack, + int temps, + int extra_args, + int monitors, + int callee_params, + int callee_locals, + bool is_top_frame) { // Note: This calculation must exactly parallel the frame setup // in InterpreterGenerator::generate_fixed_frame. - // If f!=NULL, set up the following variables: - // - Lmethod - // - Llocals - // - Lmonitors (to the indicated number of monitors) - // - Lesp (to the indicated number of temps) - // The frame f (if not NULL) on entry is a description of the caller of the frame - // we are about to layout. We are guaranteed that we will be able to fill in a - // new interpreter frame as its callee (i.e. the stack space is allocated and - // the amount was determined by an earlier call to this method with f == NULL). - // On return f (if not NULL) while describe the interpreter frame we just layed out. - int monitor_size = moncount * frame::interpreter_frame_monitor_size(); - int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); + int monitor_size = monitors * frame::interpreter_frame_monitor_size(); assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); + // // Note: if you look closely this appears to be doing something much different // than generate_fixed_frame. What is happening is this. On sparc we have to do @@ -1619,146 +1605,171 @@ // there is no sense in messing working code. // - int rounded_cls = round_to((callee_local_count - callee_param_count), WordsPerLong); + int rounded_cls = round_to((callee_locals - callee_params), WordsPerLong); assert(rounded_cls == round_to(rounded_cls, WordsPerLong), "must align"); - int raw_frame_size = size_activation_helper(rounded_cls, method->max_stack(), - monitor_size); + int raw_frame_size = size_activation_helper(rounded_cls, max_stack, monitor_size); - if (interpreter_frame != NULL) { - // The skeleton frame must already look like an interpreter frame - // even if not fully filled out. - assert(interpreter_frame->is_interpreted_frame(), "Must be interpreted frame"); - - intptr_t* fp = interpreter_frame->fp(); + return raw_frame_size; +} - JavaThread* thread = JavaThread::current(); - RegisterMap map(thread, false); - // More verification that skeleton frame is properly walkable - assert(fp == caller->sp(), "fp must match"); - - intptr_t* montop = fp - rounded_vm_local_words; +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_local_count, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + // Set up the following variables: + // - Lmethod + // - Llocals + // - Lmonitors (to the indicated number of monitors) + // - Lesp (to the indicated number of temps) + // The frame caller on entry is a description of the caller of the + // frame we are about to layout. We are guaranteed that we will be + // able to fill in a new interpreter frame as its callee (i.e. the + // stack space is allocated and the amount was determined by an + // earlier call to the size_activation() method). On return caller + // while describe the interpreter frame we just layed out. - // preallocate monitors (cf. __ add_monitor_to_stack) - intptr_t* monitors = montop - monitor_size; + // The skeleton frame must already look like an interpreter frame + // even if not fully filled out. + assert(interpreter_frame->is_interpreted_frame(), "Must be interpreted frame"); + + int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); + int monitor_size = moncount * frame::interpreter_frame_monitor_size(); + assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); + + intptr_t* fp = interpreter_frame->fp(); - // preallocate stack space - intptr_t* esp = monitors - 1 - - (tempcount * Interpreter::stackElementWords) - - popframe_extra_args; + JavaThread* thread = JavaThread::current(); + RegisterMap map(thread, false); + // More verification that skeleton frame is properly walkable + assert(fp == caller->sp(), "fp must match"); + + intptr_t* montop = fp - rounded_vm_local_words; + + // preallocate monitors (cf. __ add_monitor_to_stack) + intptr_t* monitors = montop - monitor_size; + + // preallocate stack space + intptr_t* esp = monitors - 1 - + (tempcount * Interpreter::stackElementWords) - + popframe_extra_args; - int local_words = method->max_locals() * Interpreter::stackElementWords; - NEEDS_CLEANUP; - intptr_t* locals; - if (caller->is_interpreted_frame()) { - // Can force the locals area to end up properly overlapping the top of the expression stack. - intptr_t* Lesp_ptr = caller->interpreter_frame_tos_address() - 1; - // Note that this computation means we replace size_of_parameters() values from the caller - // interpreter frame's expression stack with our argument locals - int parm_words = caller_actual_parameters * Interpreter::stackElementWords; - locals = Lesp_ptr + parm_words; - int delta = local_words - parm_words; - int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0; - *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS; - if (!is_bottom_frame) { - // Llast_SP is set below for the current frame to SP (with the - // extra space for the callee's locals). Here we adjust - // Llast_SP for the caller's frame, removing the extra space - // for the current method's locals. - *caller->register_addr(Llast_SP) = *interpreter_frame->register_addr(I5_savedSP); - } else { - assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP"); - } + int local_words = method->max_locals() * Interpreter::stackElementWords; + NEEDS_CLEANUP; + intptr_t* locals; + if (caller->is_interpreted_frame()) { + // Can force the locals area to end up properly overlapping the top of the expression stack. + intptr_t* Lesp_ptr = caller->interpreter_frame_tos_address() - 1; + // Note that this computation means we replace size_of_parameters() values from the caller + // interpreter frame's expression stack with our argument locals + int parm_words = caller_actual_parameters * Interpreter::stackElementWords; + locals = Lesp_ptr + parm_words; + int delta = local_words - parm_words; + int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0; + *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS; + if (!is_bottom_frame) { + // Llast_SP is set below for the current frame to SP (with the + // extra space for the callee's locals). Here we adjust + // Llast_SP for the caller's frame, removing the extra space + // for the current method's locals. + *caller->register_addr(Llast_SP) = *interpreter_frame->register_addr(I5_savedSP); } else { - assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases"); - // Don't have Lesp available; lay out locals block in the caller - // adjacent to the register window save area. - // - // Compiled frames do not allocate a varargs area which is why this if - // statement is needed. - // - if (caller->is_compiled_frame()) { - locals = fp + frame::register_save_words + local_words - 1; - } else { - locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1; - } - if (!caller->is_entry_frame()) { - // Caller wants his own SP back - int caller_frame_size = caller->cb()->frame_size(); - *interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS; + assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP"); + } + } else { + assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases"); + // Don't have Lesp available; lay out locals block in the caller + // adjacent to the register window save area. + // + // Compiled frames do not allocate a varargs area which is why this if + // statement is needed. + // + if (caller->is_compiled_frame()) { + locals = fp + frame::register_save_words + local_words - 1; + } else { + locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1; + } + if (!caller->is_entry_frame()) { + // Caller wants his own SP back + int caller_frame_size = caller->cb()->frame_size(); + *interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS; + } + } + if (TraceDeoptimization) { + if (caller->is_entry_frame()) { + // make sure I5_savedSP and the entry frames notion of saved SP + // agree. This assertion duplicate a check in entry frame code + // but catches the failure earlier. + assert(*caller->register_addr(Lscratch) == *interpreter_frame->register_addr(I5_savedSP), + "would change callers SP"); + } + if (caller->is_entry_frame()) { + tty->print("entry "); + } + if (caller->is_compiled_frame()) { + tty->print("compiled "); + if (caller->is_deoptimized_frame()) { + tty->print("(deopt) "); } } - if (TraceDeoptimization) { - if (caller->is_entry_frame()) { - // make sure I5_savedSP and the entry frames notion of saved SP - // agree. This assertion duplicate a check in entry frame code - // but catches the failure earlier. - assert(*caller->register_addr(Lscratch) == *interpreter_frame->register_addr(I5_savedSP), - "would change callers SP"); - } - if (caller->is_entry_frame()) { - tty->print("entry "); - } - if (caller->is_compiled_frame()) { - tty->print("compiled "); - if (caller->is_deoptimized_frame()) { - tty->print("(deopt) "); - } - } - if (caller->is_interpreted_frame()) { - tty->print("interpreted "); - } - tty->print_cr("caller fp=0x%x sp=0x%x", caller->fp(), caller->sp()); - tty->print_cr("save area = 0x%x, 0x%x", caller->sp(), caller->sp() + 16); - tty->print_cr("save area = 0x%x, 0x%x", caller->fp(), caller->fp() + 16); - tty->print_cr("interpreter fp=0x%x sp=0x%x", interpreter_frame->fp(), interpreter_frame->sp()); - tty->print_cr("save area = 0x%x, 0x%x", interpreter_frame->sp(), interpreter_frame->sp() + 16); - tty->print_cr("save area = 0x%x, 0x%x", interpreter_frame->fp(), interpreter_frame->fp() + 16); - tty->print_cr("Llocals = 0x%x", locals); - tty->print_cr("Lesp = 0x%x", esp); - tty->print_cr("Lmonitors = 0x%x", monitors); + if (caller->is_interpreted_frame()) { + tty->print("interpreted "); } + tty->print_cr("caller fp=0x%x sp=0x%x", caller->fp(), caller->sp()); + tty->print_cr("save area = 0x%x, 0x%x", caller->sp(), caller->sp() + 16); + tty->print_cr("save area = 0x%x, 0x%x", caller->fp(), caller->fp() + 16); + tty->print_cr("interpreter fp=0x%x sp=0x%x", interpreter_frame->fp(), interpreter_frame->sp()); + tty->print_cr("save area = 0x%x, 0x%x", interpreter_frame->sp(), interpreter_frame->sp() + 16); + tty->print_cr("save area = 0x%x, 0x%x", interpreter_frame->fp(), interpreter_frame->fp() + 16); + tty->print_cr("Llocals = 0x%x", locals); + tty->print_cr("Lesp = 0x%x", esp); + tty->print_cr("Lmonitors = 0x%x", monitors); + } - if (method->max_locals() > 0) { - assert(locals < caller->sp() || locals >= (caller->sp() + 16), "locals in save area"); - assert(locals < caller->fp() || locals > (caller->fp() + 16), "locals in save area"); - assert(locals < interpreter_frame->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area"); - assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); - } + if (method->max_locals() > 0) { + assert(locals < caller->sp() || locals >= (caller->sp() + 16), "locals in save area"); + assert(locals < caller->fp() || locals > (caller->fp() + 16), "locals in save area"); + assert(locals < interpreter_frame->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area"); + assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); + } #ifdef _LP64 - assert(*interpreter_frame->register_addr(I5_savedSP) & 1, "must be odd"); + assert(*interpreter_frame->register_addr(I5_savedSP) & 1, "must be odd"); #endif - *interpreter_frame->register_addr(Lmethod) = (intptr_t) method; - *interpreter_frame->register_addr(Llocals) = (intptr_t) locals; - *interpreter_frame->register_addr(Lmonitors) = (intptr_t) monitors; - *interpreter_frame->register_addr(Lesp) = (intptr_t) esp; - // Llast_SP will be same as SP as there is no adapter space - *interpreter_frame->register_addr(Llast_SP) = (intptr_t) interpreter_frame->sp() - STACK_BIAS; - *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); + *interpreter_frame->register_addr(Lmethod) = (intptr_t) method; + *interpreter_frame->register_addr(Llocals) = (intptr_t) locals; + *interpreter_frame->register_addr(Lmonitors) = (intptr_t) monitors; + *interpreter_frame->register_addr(Lesp) = (intptr_t) esp; + // Llast_SP will be same as SP as there is no adapter space + *interpreter_frame->register_addr(Llast_SP) = (intptr_t) interpreter_frame->sp() - STACK_BIAS; + *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); #ifdef FAST_DISPATCH - *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); + *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); #endif #ifdef ASSERT - BasicObjectLock* mp = (BasicObjectLock*)monitors; - - assert(interpreter_frame->interpreter_frame_method() == method, "method matches"); - assert(interpreter_frame->interpreter_frame_local_at(9) == (intptr_t *)((intptr_t)locals - (9 * Interpreter::stackElementSize)), "locals match"); - assert(interpreter_frame->interpreter_frame_monitor_end() == mp, "monitor_end matches"); - assert(((intptr_t *)interpreter_frame->interpreter_frame_monitor_begin()) == ((intptr_t *)mp)+monitor_size, "monitor_begin matches"); - assert(interpreter_frame->interpreter_frame_tos_address()-1 == esp, "esp matches"); + BasicObjectLock* mp = (BasicObjectLock*)monitors; - // check bounds - intptr_t* lo = interpreter_frame->sp() + (frame::memory_parameter_word_sp_offset - 1); - intptr_t* hi = interpreter_frame->fp() - rounded_vm_local_words; - assert(lo < monitors && montop <= hi, "monitors in bounds"); - assert(lo <= esp && esp < monitors, "esp in bounds"); + assert(interpreter_frame->interpreter_frame_method() == method, "method matches"); + assert(interpreter_frame->interpreter_frame_local_at(9) == (intptr_t *)((intptr_t)locals - (9 * Interpreter::stackElementSize)), "locals match"); + assert(interpreter_frame->interpreter_frame_monitor_end() == mp, "monitor_end matches"); + assert(((intptr_t *)interpreter_frame->interpreter_frame_monitor_begin()) == ((intptr_t *)mp)+monitor_size, "monitor_begin matches"); + assert(interpreter_frame->interpreter_frame_tos_address()-1 == esp, "esp matches"); + + // check bounds + intptr_t* lo = interpreter_frame->sp() + (frame::memory_parameter_word_sp_offset - 1); + intptr_t* hi = interpreter_frame->fp() - rounded_vm_local_words; + assert(lo < monitors && montop <= hi, "monitors in bounds"); + assert(lo <= esp && esp < monitors, "esp in bounds"); #endif // ASSERT - } - - return raw_frame_size; } //---------------------------------------------------------------------------------------------------- diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -288,7 +288,7 @@ // build frame ciMethod* m = compilation()->method(); - __ build_frame(initial_frame_size_in_bytes()); + __ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); // OSR buffer is // @@ -376,7 +376,7 @@ } // This specifies the rsp decrement needed to build the frame -int LIR_Assembler::initial_frame_size_in_bytes() { +int LIR_Assembler::initial_frame_size_in_bytes() const { // if rounding, must let FrameMap know! // The frame_map records size in slots (32bit word) diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -349,13 +349,14 @@ } -void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { +void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { + assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect"); // Make sure there is enough stack space for this method's activation. // Note that we do this before doing an enter(). This matches the // ordering of C2's stack overflow check / rsp decrement and allows // the SharedRuntime stack overflow handling to be consistent // between the two compilers. - generate_stack_overflow_check(frame_size_in_bytes); + generate_stack_overflow_check(bang_size_in_bytes); push(rbp); #ifdef TIERED diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2342,29 +2342,42 @@ "Stack top out of range"); } -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, // - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_locals, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { - - assert(popframe_extra_args == 0, "FIX ME"); - // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() - // does as far as allocating an interpreter frame. - // If interpreter_frame!=NULL, set up the method, locals, and monitors. - // The frame interpreter_frame, if not NULL, is guaranteed to be the right size, - // as determined by a previous call to this method. - // It is also guaranteed to be walkable even though it is in a skeletal state + +static int frame_size_helper(int max_stack, + int tempcount, + int moncount, + int callee_param_count, + int callee_locals, + bool is_top_frame, + int& monitor_size, + int& full_frame_size) { + int extra_locals_size = (callee_locals - callee_param_count) * BytesPerWord; + monitor_size = sizeof(BasicObjectLock) * moncount; + + // First calculate the frame size without any java expression stack + int short_frame_size = size_activation_helper(extra_locals_size, + monitor_size); + + // Now with full size expression stack + full_frame_size = short_frame_size + max_stack * BytesPerWord; + + // and now with only live portion of the expression stack + short_frame_size = short_frame_size + tempcount * BytesPerWord; + + // the size the activation is right now. Only top frame is full size + int frame_size = (is_top_frame ? full_frame_size : short_frame_size); + return frame_size; +} + +int AbstractInterpreter::size_activation(int max_stack, + int tempcount, + int extra_args, + int moncount, + int callee_param_count, + int callee_locals, + bool is_top_frame) { + assert(extra_args == 0, "FIX ME"); // NOTE: return size is in words not bytes - // NOTE: tempcount is the current size of the java expression stack. For top most - // frames we will allocate a full sized expression stack and not the curback - // version that non-top frames have. // Calculate the amount our frame will be adjust by the callee. For top frame // this is zero. @@ -2374,87 +2387,102 @@ // to it. So it ignores last_frame_adjust value. Seems suspicious as far // as getting sender_sp correct. - int extra_locals_size = (callee_locals - callee_param_count) * BytesPerWord; - int monitor_size = sizeof(BasicObjectLock) * moncount; - - // First calculate the frame size without any java expression stack - int short_frame_size = size_activation_helper(extra_locals_size, - monitor_size); - - // Now with full size expression stack - int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord; - - // and now with only live portion of the expression stack - short_frame_size = short_frame_size + tempcount * BytesPerWord; - - // the size the activation is right now. Only top frame is full size - int frame_size = (is_top_frame ? full_frame_size : short_frame_size); - - if (interpreter_frame != NULL) { + int unused_monitor_size = 0; + int unused_full_frame_size = 0; + return frame_size_helper(max_stack, tempcount, moncount, callee_param_count, callee_locals, + is_top_frame, unused_monitor_size, unused_full_frame_size)/BytesPerWord; +} + +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, // + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_locals, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + + assert(popframe_extra_args == 0, "FIX ME"); + // NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() + // does as far as allocating an interpreter frame. + // Set up the method, locals, and monitors. + // The frame interpreter_frame is guaranteed to be the right size, + // as determined by a previous call to the size_activation() method. + // It is also guaranteed to be walkable even though it is in a skeletal state + // NOTE: tempcount is the current size of the java expression stack. For top most + // frames we will allocate a full sized expression stack and not the curback + // version that non-top frames have. + + int monitor_size = 0; + int full_frame_size = 0; + int frame_size = frame_size_helper(method->max_stack(), tempcount, moncount, callee_param_count, callee_locals, + is_top_frame, monitor_size, full_frame_size); + #ifdef ASSERT - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); #endif - // MUCHO HACK - - intptr_t* frame_bottom = (intptr_t*) ((intptr_t)interpreter_frame->sp() - (full_frame_size - frame_size)); - - /* Now fillin the interpreterState object */ - - // The state object is the first thing on the frame and easily located - - interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter)); - - - // Find the locals pointer. This is rather simple on x86 because there is no - // confusing rounding at the callee to account for. We can trivially locate - // our locals based on the current fp(). - // Note: the + 2 is for handling the "static long no_params() method" issue. - // (too bad I don't really remember that issue well...) - - intptr_t* locals; - // If the caller is interpreted we need to make sure that locals points to the first - // argument that the caller passed and not in an area where the stack might have been extended. - // because the stack to stack to converter needs a proper locals value in order to remove the - // arguments from the caller and place the result in the proper location. Hmm maybe it'd be - // simpler if we simply stored the result in the BytecodeInterpreter object and let the c++ code - // adjust the stack?? HMMM QQQ - // - if (caller->is_interpreted_frame()) { - // locals must agree with the caller because it will be used to set the - // caller's tos when we return. - interpreterState prev = caller->get_interpreterState(); - // stack() is prepushed. - locals = prev->stack() + method->size_of_parameters(); - // locals = caller->unextended_sp() + (method->size_of_parameters() - 1); - if (locals != interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2) { - // os::breakpoint(); - } - } else { - // this is where a c2i would have placed locals (except for the +2) - locals = interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2; + // MUCHO HACK + + intptr_t* frame_bottom = (intptr_t*) ((intptr_t)interpreter_frame->sp() - (full_frame_size - frame_size)); + + /* Now fillin the interpreterState object */ + + // The state object is the first thing on the frame and easily located + + interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter)); + + + // Find the locals pointer. This is rather simple on x86 because there is no + // confusing rounding at the callee to account for. We can trivially locate + // our locals based on the current fp(). + // Note: the + 2 is for handling the "static long no_params() method" issue. + // (too bad I don't really remember that issue well...) + + intptr_t* locals; + // If the caller is interpreted we need to make sure that locals points to the first + // argument that the caller passed and not in an area where the stack might have been extended. + // because the stack to stack to converter needs a proper locals value in order to remove the + // arguments from the caller and place the result in the proper location. Hmm maybe it'd be + // simpler if we simply stored the result in the BytecodeInterpreter object and let the c++ code + // adjust the stack?? HMMM QQQ + // + if (caller->is_interpreted_frame()) { + // locals must agree with the caller because it will be used to set the + // caller's tos when we return. + interpreterState prev = caller->get_interpreterState(); + // stack() is prepushed. + locals = prev->stack() + method->size_of_parameters(); + // locals = caller->unextended_sp() + (method->size_of_parameters() - 1); + if (locals != interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2) { + // os::breakpoint(); } - - intptr_t* monitor_base = (intptr_t*) cur_state; - intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); - /* +1 because stack is always prepushed */ - intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (tempcount + 1) * BytesPerWord); - - - BytecodeInterpreter::layout_interpreterState(cur_state, - caller, - interpreter_frame, - method, - locals, - stack, - stack_base, - monitor_base, - frame_bottom, - is_top_frame); - - // BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp()); + } else { + // this is where a c2i would have placed locals (except for the +2) + locals = interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2; } - return frame_size/BytesPerWord; + + intptr_t* monitor_base = (intptr_t*) cur_state; + intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); + /* +1 because stack is always prepushed */ + intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (tempcount + 1) * BytesPerWord); + + + BytecodeInterpreter::layout_interpreterState(cur_state, + caller, + interpreter_frame, + method, + locals, + stack, + stack_base, + monitor_base, + frame_bottom, + is_top_frame); + + // BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp()); } bool AbstractInterpreter::can_be_compiled(methodHandle m) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1051,7 +1051,7 @@ // was post-decremented.) Skip this address by starting at i=1, and // touch a few more pages below. N.B. It is important to touch all // the way down to and including i=StackShadowPages. - for (int i = 1; i <= StackShadowPages; i++) { + for (int i = 1; i < StackShadowPages; i++) { // this could be any sized move but this is can be a debugging crumb // so the bigger the better. movptr(Address(tmp, (-i*os::vm_page_size())), size ); @@ -6093,7 +6093,7 @@ // C2 compiled method's prolog code. -void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode_24b) { +void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b) { // WARNING: Initial instruction MUST be 5 bytes or longer so that // NativeJump::patch_verified_entry will be able to patch out the entry @@ -6101,18 +6101,20 @@ // the frame allocation can be either 3 or 6 bytes. So if we don't do // stack bang then we must use the 6 byte frame allocation even if // we have no frame. :-( + assert(stack_bang_size >= framesize || stack_bang_size <= 0, "stack bang size incorrect"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove word for return addr framesize -= wordSize; + stack_bang_size -= wordSize; // Calls to C2R adapters often do not accept exceptional returns. // We require that their callers must bang for them. But be careful, because // some VM calls (such as call site linkage) can use several kilobytes of // stack. But the stack safety zone should account for that. // See bugs 4446381, 4468289, 4497237. - if (stack_bang) { - generate_stack_overflow_check(framesize); + if (stack_bang_size > 0) { + generate_stack_overflow_check(stack_bang_size); // We always push rbp, so that on return to interpreter rbp, will be // restored correctly and we can correct the stack. diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -1170,7 +1170,7 @@ void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } // C2 compiled method's prolog code. - void verified_entry(int framesize, bool stack_bang, bool fp_mode_24b); + void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b); // clear memory of size 'cnt' qwords, starting at 'base'. void clear_mem(Register base, Register cnt, Register rtmp); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -3014,11 +3014,15 @@ // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Stack bang to make sure there's enough room for these interpreter frames. +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ bang_stack_size(rbx, rcx); } +#endif // Load array of frame pcs into ECX __ movptr(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); @@ -3240,12 +3244,15 @@ // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Stack bang to make sure there's enough room for these interpreter frames. +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ bang_stack_size(rbx, rcx); } - +#endif // Load array of frame pcs into ECX __ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -3484,11 +3484,15 @@ // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Stack bang to make sure there's enough room for these interpreter frames. +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. if (UseStackBanging) { __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ bang_stack_size(rbx, rcx); } +#endif // Load address of array of frame pcs into rcx __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); @@ -3682,11 +3686,15 @@ // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Stack bang to make sure there's enough room for these interpreter frames. +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ bang_stack_size(rbx, rcx); } +#endif // Load address of array of frame pcs into rcx (address*) __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1997, 2014, 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. + * + */ + +#include "precompiled.hpp" +#include "ci/ciMethod.hpp" +#include "interpreter/interpreter.hpp" +#include "runtime/frame.inline.hpp" + +#ifndef CC_INTERP + +// asm based interpreter deoptimization helpers +int AbstractInterpreter::size_activation(int max_stack, + int temps, + int extra_args, + int monitors, + int callee_params, + int callee_locals, + bool is_top_frame) { + // Note: This calculation must exactly parallel the frame setup + // in AbstractInterpreterGenerator::generate_method_entry. + + // fixed size of an interpreter frame: + int overhead = frame::sender_sp_offset - + frame::interpreter_frame_initial_sp_offset; + // Our locals were accounted for by the caller (or last_frame_adjust + // on the transistion) Since the callee parameters already account + // for the callee's params we only need to account for the extra + // locals. + int size = overhead + + (callee_locals - callee_params)*Interpreter::stackElementWords + + monitors * frame::interpreter_frame_monitor_size() + + temps* Interpreter::stackElementWords + extra_args; + + return size; +} + +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_locals, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + // The frame interpreter_frame is guaranteed to be the right size, + // as determined by a previous call to the size_activation() method. + // It is also guaranteed to be walkable even though it is in a + // skeletal state + + int max_locals = method->max_locals() * Interpreter::stackElementWords; + int extra_locals = (method->max_locals() - method->size_of_parameters()) * + Interpreter::stackElementWords; + +#ifdef ASSERT + if (!EnableInvokeDynamic) { + // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? + // Probably, since deoptimization doesn't work yet. + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); + } + assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); +#endif + + interpreter_frame->interpreter_frame_set_method(method); + // NOTE the difference in using sender_sp and + // interpreter_frame_sender_sp interpreter_frame_sender_sp is + // the original sp of the caller (the unextended_sp) and + // sender_sp is fp+8/16 (32bit/64bit) XXX + intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; + +#ifdef ASSERT + if (caller->is_interpreted_frame()) { + assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); + } +#endif + + interpreter_frame->interpreter_frame_set_locals(locals); + BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); + BasicObjectLock* monbot = montop - moncount; + interpreter_frame->interpreter_frame_set_monitor_end(monbot); + + // Set last_sp + intptr_t* esp = (intptr_t*) monbot - + tempcount*Interpreter::stackElementWords - + popframe_extra_args; + interpreter_frame->interpreter_frame_set_last_sp(esp); + + // All frames but the initial (oldest) interpreter frame we fill in have + // a value for sender_sp that allows walking the stack but isn't + // truly correct. Correct the value here. + if (extra_locals != 0 && + interpreter_frame->sender_sp() == + interpreter_frame->interpreter_frame_sender_sp()) { + interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + + extra_locals); + } + *interpreter_frame->interpreter_frame_cache_addr() = + method->constants()->cache(); +} + +#endif // CC_INTERP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1686,91 +1686,6 @@ return overhead_size + method_stack + stub_code; } -// asm based interpreter deoptimization helpers - -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_locals, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { - // Note: This calculation must exactly parallel the frame setup - // in AbstractInterpreterGenerator::generate_method_entry. - // If interpreter_frame!=NULL, set up the method, locals, and monitors. - // The frame interpreter_frame, if not NULL, is guaranteed to be the right size, - // as determined by a previous call to this method. - // It is also guaranteed to be walkable even though it is in a skeletal state - // NOTE: return size is in words not bytes - - // fixed size of an interpreter frame: - int max_locals = method->max_locals() * Interpreter::stackElementWords; - int extra_locals = (method->max_locals() - method->size_of_parameters()) * - Interpreter::stackElementWords; - - int overhead = frame::sender_sp_offset - frame::interpreter_frame_initial_sp_offset; - - // Our locals were accounted for by the caller (or last_frame_adjust on the transistion) - // Since the callee parameters already account for the callee's params we only need to account for - // the extra locals. - - - int size = overhead + - ((callee_locals - callee_param_count)*Interpreter::stackElementWords) + - (moncount*frame::interpreter_frame_monitor_size()) + - tempcount*Interpreter::stackElementWords + popframe_extra_args; - - if (interpreter_frame != NULL) { -#ifdef ASSERT - if (!EnableInvokeDynamic) - // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? - // Probably, since deoptimization doesn't work yet. - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); - assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); -#endif - - interpreter_frame->interpreter_frame_set_method(method); - // NOTE the difference in using sender_sp and interpreter_frame_sender_sp - // interpreter_frame_sender_sp is the original sp of the caller (the unextended_sp) - // and sender_sp is fp+8 - intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; - -#ifdef ASSERT - if (caller->is_interpreted_frame()) { - assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); - } -#endif - - interpreter_frame->interpreter_frame_set_locals(locals); - BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); - BasicObjectLock* monbot = montop - moncount; - interpreter_frame->interpreter_frame_set_monitor_end(monbot); - - // Set last_sp - intptr_t* rsp = (intptr_t*) monbot - - tempcount*Interpreter::stackElementWords - - popframe_extra_args; - interpreter_frame->interpreter_frame_set_last_sp(rsp); - - // All frames but the initial (oldest) interpreter frame we fill in have a - // value for sender_sp that allows walking the stack but isn't - // truly correct. Correct the value here. - - if (extra_locals != 0 && - interpreter_frame->sender_sp() == interpreter_frame->interpreter_frame_sender_sp() ) { - interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + extra_locals); - } - *interpreter_frame->interpreter_frame_cache_addr() = - method->constants()->cache(); - } - return size; -} - - //------------------------------------------------------------------------------------------------------------------------ // Exceptions diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1695,87 +1695,6 @@ return (overhead_size + method_stack + stub_code); } -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_locals, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { - // Note: This calculation must exactly parallel the frame setup - // in AbstractInterpreterGenerator::generate_method_entry. - // If interpreter_frame!=NULL, set up the method, locals, and monitors. - // The frame interpreter_frame, if not NULL, is guaranteed to be the - // right size, as determined by a previous call to this method. - // It is also guaranteed to be walkable even though it is in a skeletal state - - // fixed size of an interpreter frame: - int max_locals = method->max_locals() * Interpreter::stackElementWords; - int extra_locals = (method->max_locals() - method->size_of_parameters()) * - Interpreter::stackElementWords; - - int overhead = frame::sender_sp_offset - - frame::interpreter_frame_initial_sp_offset; - // Our locals were accounted for by the caller (or last_frame_adjust - // on the transistion) Since the callee parameters already account - // for the callee's params we only need to account for the extra - // locals. - int size = overhead + - (callee_locals - callee_param_count)*Interpreter::stackElementWords + - moncount * frame::interpreter_frame_monitor_size() + - tempcount* Interpreter::stackElementWords + popframe_extra_args; - if (interpreter_frame != NULL) { -#ifdef ASSERT - if (!EnableInvokeDynamic) - // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? - // Probably, since deoptimization doesn't work yet. - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); - assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); -#endif - - interpreter_frame->interpreter_frame_set_method(method); - // NOTE the difference in using sender_sp and - // interpreter_frame_sender_sp interpreter_frame_sender_sp is - // the original sp of the caller (the unextended_sp) and - // sender_sp is fp+16 XXX - intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; - -#ifdef ASSERT - if (caller->is_interpreted_frame()) { - assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); - } -#endif - - interpreter_frame->interpreter_frame_set_locals(locals); - BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); - BasicObjectLock* monbot = montop - moncount; - interpreter_frame->interpreter_frame_set_monitor_end(monbot); - - // Set last_sp - intptr_t* esp = (intptr_t*) monbot - - tempcount*Interpreter::stackElementWords - - popframe_extra_args; - interpreter_frame->interpreter_frame_set_last_sp(esp); - - // All frames but the initial (oldest) interpreter frame we fill in have - // a value for sender_sp that allows walking the stack but isn't - // truly correct. Correct the value here. - if (extra_locals != 0 && - interpreter_frame->sender_sp() == - interpreter_frame->interpreter_frame_sender_sp()) { - interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + - extra_locals); - } - *interpreter_frame->interpreter_frame_cache_addr() = - method->constants()->cache(); - } - return size; -} - //----------------------------------------------------------------------------- // Exceptions diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Apr 23 10:12:34 2014 +0200 @@ -512,14 +512,15 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); + int bangsize = C->bang_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove wordSize for return addr which is already pushed. framesize -= wordSize; - if (C->need_stack_bang(framesize)) { + if (C->need_stack_bang(bangsize)) { framesize -= wordSize; - st->print("# stack bang"); + st->print("# stack bang (%d bytes)", bangsize); st->print("\n\t"); st->print("PUSH EBP\t# Save EBP"); if (framesize) { @@ -563,9 +564,10 @@ Compile* C = ra_->C; MacroAssembler _masm(&cbuf); - int framesize = C->frame_slots() << LogBytesPerInt; - - __ verified_entry(framesize, C->need_stack_bang(framesize), C->in_24_bit_fp_mode()); + int framesize = C->frame_size_in_bytes(); + int bangsize = C->bang_size_in_bytes(); + + __ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode()); C->set_frame_complete(cbuf.insts_size()); @@ -589,7 +591,7 @@ #ifndef PRODUCT void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { Compile *C = ra_->C; - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove two words for return addr and rbp, framesize -= 2*wordSize; @@ -629,7 +631,7 @@ masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove two words for return addr and rbp, framesize -= 2*wordSize; @@ -663,7 +665,7 @@ if (C->max_vector_size() > 16) size += 3; // vzeroupper if (do_polling() && C->is_method_compilation()) size += 6; - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove two words for return addr and rbp, framesize -= 2*wordSize; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Apr 23 10:12:34 2014 +0200 @@ -713,14 +713,15 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); + int bangsize = C->bang_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove wordSize for return addr which is already pushed. framesize -= wordSize; - if (C->need_stack_bang(framesize)) { + if (C->need_stack_bang(bangsize)) { framesize -= wordSize; - st->print("# stack bang"); + st->print("# stack bang (%d bytes)", bangsize); st->print("\n\t"); st->print("pushq rbp\t# Save rbp"); if (framesize) { @@ -751,9 +752,10 @@ Compile* C = ra_->C; MacroAssembler _masm(&cbuf); - int framesize = C->frame_slots() << LogBytesPerInt; - - __ verified_entry(framesize, C->need_stack_bang(framesize), false); + int framesize = C->frame_size_in_bytes(); + int bangsize = C->bang_size_in_bytes(); + + __ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, false); C->set_frame_complete(cbuf.insts_size()); @@ -786,7 +788,7 @@ st->cr(); st->print("\t"); } - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove word for return adr already pushed // and RBP @@ -822,7 +824,7 @@ __ vzeroupper(); } - int framesize = C->frame_slots() << LogBytesPerInt; + int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove word for return adr already pushed // and RBP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -916,17 +916,32 @@ return (InterpreterFrame *) fp; } -int AbstractInterpreter::layout_activation(Method* method, - int tempcount, - int popframe_extra_args, - int moncount, - int caller_actual_parameters, - int callee_param_count, - int callee_locals, - frame* caller, - frame* interpreter_frame, - bool is_top_frame, - bool is_bottom_frame) { +int AbstractInterpreter::size_activation(int max_stack, + int tempcount, + int extra_args, + int moncount, + int callee_param_count, + int callee_locals, + bool is_top_frame) { + int header_words = InterpreterFrame::header_words; + int monitor_words = moncount * frame::interpreter_frame_monitor_size(); + int stack_words = is_top_frame ? max_stack : tempcount; + int callee_extra_locals = callee_locals - callee_param_count; + + return header_words + monitor_words + stack_words + callee_extra_locals; +} + +void AbstractInterpreter::layout_activation(Method* method, + int tempcount, + int popframe_extra_args, + int moncount, + int caller_actual_parameters, + int callee_param_count, + int callee_locals, + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { assert(popframe_extra_args == 0, "what to do?"); assert(!is_top_frame || (!callee_locals && !callee_param_count), "top frame should have no caller"); @@ -935,39 +950,31 @@ // does (the full InterpreterFrame::build, that is, not the // one that creates empty frames for the deoptimizer). // - // If interpreter_frame is not NULL then it will be filled in. - // It's size is determined by a previous call to this method, - // so it should be correct. + // interpreter_frame will be filled in. It's size is determined by + // a previous call to the size_activation() method, // // Note that tempcount is the current size of the expression // stack. For top most frames we will allocate a full sized // expression stack and not the trimmed version that non-top // frames have. - int header_words = InterpreterFrame::header_words; int monitor_words = moncount * frame::interpreter_frame_monitor_size(); - int stack_words = is_top_frame ? method->max_stack() : tempcount; - int callee_extra_locals = callee_locals - callee_param_count; - - if (interpreter_frame) { - intptr_t *locals = interpreter_frame->fp() + method->max_locals(); - interpreterState istate = interpreter_frame->get_interpreterState(); - intptr_t *monitor_base = (intptr_t*) istate; - intptr_t *stack_base = monitor_base - monitor_words; - intptr_t *stack = stack_base - tempcount - 1; + intptr_t *locals = interpreter_frame->fp() + method->max_locals(); + interpreterState istate = interpreter_frame->get_interpreterState(); + intptr_t *monitor_base = (intptr_t*) istate; + intptr_t *stack_base = monitor_base - monitor_words; + intptr_t *stack = stack_base - tempcount - 1; - BytecodeInterpreter::layout_interpreterState(istate, - caller, - NULL, - method, - locals, - stack, - stack_base, - monitor_base, - NULL, - is_top_frame); - } - return header_words + monitor_words + stack_words + callee_extra_locals; + BytecodeInterpreter::layout_interpreterState(istate, + caller, + NULL, + method, + locals, + stack, + stack_base, + monitor_base, + NULL, + is_top_frame); } void BytecodeInterpreter::layout_interpreterState(interpreterState istate, diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Wed Apr 23 10:12:34 2014 +0200 @@ -25,6 +25,7 @@ package com.sun.hotspot.tools.compiler; import java.io.PrintStream; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; @@ -40,6 +41,7 @@ private int endNodes; private int endLiveNodes; private double timeStamp; + private long inlineId; CallSite() { } @@ -94,7 +96,7 @@ public void print(PrintStream stream, int indent) { emit(stream, indent); - String m = getMethod().getHolder().replace('/', '.') + "::" + getMethod().getName(); + String m = getMethod().getHolder() + "::" + getMethod().getName(); if (getReason() == null) { stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); @@ -214,4 +216,45 @@ return timeStamp; } + private boolean matches(CallSite other) { + // Every late inline call site has a unique inline id. If the + // call site we're looking for has one then use it other rely + // on method name and bci. + if (other.inlineId != 0) { + return inlineId == other.inlineId; + } + return method.equals(other.method) && bci == other.bci; + } + + public CallSite findCallSite(ArrayDeque sites) { + // Locate a late inline call site. Multiple chains of + // identical call sites with the same method name/bci are + // possible so we have to try them all until we find the late + // inline call site that has a matching inline id. + CallSite site = sites.pop(); + for (CallSite c : calls) { + if (c.matches(site)) { + if (!sites.isEmpty()) { + CallSite res = c.findCallSite(sites); + if (res != null) { + sites.push(site); + return res; + } + } else { + sites.push(site); + return c; + } + } + } + sites.push(site); + return null; + } + + public long getInlineId() { + return inlineId; + } + + public void setInlineId(long inlineId) { + this.inlineId = inlineId; + } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Wed Apr 23 10:12:34 2014 +0200 @@ -31,6 +31,7 @@ import java.io.FileReader; import java.io.Reader; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -144,9 +145,12 @@ private Stack scopes = new Stack(); private Compilation compile; private CallSite site; + private CallSite methodHandleSite; private Stack phaseStack = new Stack(); private UncommonTrapEvent currentTrap; - private Stack late_inline_scope; + private Stack lateInlineScope; + private boolean lateInlining; + long parseLong(String l) { try { @@ -330,18 +334,61 @@ } methods.put(id, m); } else if (qname.equals("call")) { - site = new CallSite(bci, method(search(atts, "method"))); + if (methodHandleSite != null) { + methodHandleSite = null; + } + Method m = method(search(atts, "method")); + if (lateInlining && scopes.size() == 0) { + // re-attempting already seen call site (late inlining for MH invokes) + if (m != site.getMethod()) { + if (bci != site.getBci()) { + System.out.println(m + " bci: " + bci); + System.out.println(site.getMethod() + " bci: " + site.getBci()); + throw new InternalError("bci mismatch after late inlining"); + } + site.setMethod(m); + } + } else { + site = new CallSite(bci, m); + } site.setCount(Integer.parseInt(search(atts, "count", "0"))); String receiver = atts.getValue("receiver"); if (receiver != null) { site.setReceiver(type(receiver)); site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count"))); } - scopes.peek().add(site); + int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0")); + if (lateInlining && scopes.size() == 0) { + // The call was added before this round of late inlining + } else if (methodHandle == 0) { + scopes.peek().add(site); + } else { + // method handle call site can be followed by another + // call (in case it is inlined). If that happens we + // discard the method handle call site. So we keep + // track of it but don't add it to the list yet. + methodHandleSite = site; + } } else if (qname.equals("regalloc")) { compile.setAttempts(Integer.parseInt(search(atts, "attempts"))); } else if (qname.equals("inline_fail")) { - scopes.peek().last().setReason(search(atts, "reason")); + if (methodHandleSite != null) { + scopes.peek().add(methodHandleSite); + methodHandleSite = null; + } + if (lateInlining && scopes.size() == 0) { + site.setReason(search(atts, "reason")); + lateInlining = false; + } else { + scopes.peek().last().setReason(search(atts, "reason")); + } + } else if (qname.equals("inline_success")) { + if (methodHandleSite != null) { + throw new InternalError("method handle site should have been replaced"); + } + if (lateInlining && scopes.size() == 0) { + site.setReason(null); + } } else if (qname.equals("failure")) { failureReason = search(atts, "reason"); } else if (qname.equals("task_done")) { @@ -371,22 +418,30 @@ // ignore for now } } else if (qname.equals("late_inline")) { - late_inline_scope = new Stack(); + long inlineId = Long.parseLong(search(atts, "inline_id")); + lateInlineScope = new Stack(); site = new CallSite(-999, method(search(atts, "method"))); - late_inline_scope.push(site); + site.setInlineId(inlineId); + lateInlineScope.push(site); } else if (qname.equals("jvms")) { // if (currentTrap != null) { currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); - } else if (late_inline_scope != null) { + } else if (lateInlineScope != null) { bci = Integer.parseInt(search(atts, "bci")); site = new CallSite(bci, method(search(atts, "method"))); - late_inline_scope.push(site); + lateInlineScope.push(site); } else { // Ignore , // , // } + } else if (qname.equals("inline_id")) { + if (methodHandleSite != null) { + throw new InternalError("method handle site should have been replaced"); + } + long id = Long.parseLong(search(atts, "id")); + site.setInlineId(id); } else if (qname.equals("nmethod")) { String id = makeId(atts); NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")), @@ -396,8 +451,18 @@ nmethods.put(id, nm); events.add(nm); } else if (qname.equals("parse")) { + if (methodHandleSite != null) { + throw new InternalError("method handle site should have been replaced"); + } Method m = method(search(atts, "method")); - if (scopes.size() == 0) { + if (lateInlining && scopes.size() == 0) { + if (site.getMethod() != m) { + System.out.println(site.getMethod()); + System.out.println(m); + throw new InternalError("Unexpected method mismatch during late inlining"); + } + } + if (scopes.size() == 0 && !lateInlining) { compile.setMethod(m); scopes.push(site); } else { @@ -427,14 +492,19 @@ if (qname.equals("parse")) { indent -= 2; scopes.pop(); + if (scopes.size() == 0) { + lateInlining = false; + } } else if (qname.equals("uncommon_trap")) { currentTrap = null; } else if (qname.equals("late_inline")) { // Populate late inlining info. - - // late_inline scopes are specified in reverse order: + if (scopes.size() != 0) { + throw new InternalError("scopes should be empty for late inline"); + } + // late inline scopes are specified in reverse order: // compiled method should be on top of stack. - CallSite caller = late_inline_scope.pop(); + CallSite caller = lateInlineScope.pop(); Method m = compile.getMethod(); if (m != caller.getMethod()) { System.out.println(m); @@ -444,28 +514,42 @@ // late_inline contains caller+bci info, convert it // to bci+callee info used by LogCompilation. - site = compile.getLateInlineCall(); + CallSite lateInlineSite = compile.getLateInlineCall(); + ArrayDeque thisCallScopes = new ArrayDeque(); do { bci = caller.getBci(); // Next inlined call. - caller = late_inline_scope.pop(); + caller = lateInlineScope.pop(); CallSite callee = new CallSite(bci, caller.getMethod()); - site.add(callee); - site = callee; - } while (!late_inline_scope.empty()); + callee.setInlineId(caller.getInlineId()); + thisCallScopes.addLast(callee); + lateInlineSite.add(callee); + lateInlineSite = callee; + } while (!lateInlineScope.empty()); + + site = compile.getCall().findCallSite(thisCallScopes); + if (site == null) { + System.out.println(caller.getMethod() + " bci: " + bci); + throw new InternalError("couldn't find call site"); + } + lateInlining = true; if (caller.getBci() != -999) { System.out.println(caller.getMethod()); throw new InternalError("broken late_inline info"); } if (site.getMethod() != caller.getMethod()) { - System.out.println(site.getMethod()); - System.out.println(caller.getMethod()); - throw new InternalError("call site and late_inline info don't match"); + if (site.getInlineId() == caller.getInlineId()) { + site.setMethod(caller.getMethod()); + } else { + System.out.println(site.getMethod()); + System.out.println(caller.getMethod()); + throw new InternalError("call site and late_inline info don't match"); + } } // late_inline is followed by parse with scopes.size() == 0, // 'site' will be pushed to scopes. - late_inline_scope = null; + lateInlineScope = null; } else if (qname.equals("task")) { types.clear(); methods.clear(); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Wed Apr 23 10:12:34 2014 +0200 @@ -51,15 +51,15 @@ String format(int osr_bci) { if (osr_bci >= 0) { - return getHolder().replace('/', '.') + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)"; + return getHolder() + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)"; } else { - return getHolder().replace('/', '.') + "::" + getName() + " (" + getBytes() + " bytes)"; + return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)"; } } @Override public String toString() { - return getHolder().replace('/', '.') + "::" + getName() + " (" + getBytes() + " bytes)"; + return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)"; } public String getHolder() { @@ -117,4 +117,14 @@ public void setFlags(String flags) { this.flags = flags; } + + @Override + public boolean equals(Object o) { + if (o instanceof Method) { + Method other = (Method)o; + return holder.equals(other.holder) && name.equals(other.name) && + arguments.equals(other.arguments) && returnType.equals(other.returnType); + } + return false; + } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/adlc/output_h.cpp --- a/hotspot/src/share/vm/adlc/output_h.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/adlc/output_h.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1613,21 +1613,20 @@ // Each instruction attribute results in a virtual call of same name. // The ins_cost is not handled here. Attribute *attr = instr->_attribs; - bool avoid_back_to_back = false; + Attribute *avoid_back_to_back_attr = NULL; while (attr != NULL) { - if (strcmp (attr->_ident, "ins_cost") != 0 && + if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) { + fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val); + } else if (strcmp (attr->_ident, "ins_cost") != 0 && strncmp(attr->_ident, "ins_field_", 10) != 0 && // Must match function in node.hpp: return type bool, no prefix "ins_". strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") != 0 && strcmp (attr->_ident, "ins_short_branch") != 0) { fprintf(fp, " virtual int %s() const { return %s; }\n", attr->_ident, attr->_val); } - // Check value for ins_avoid_back_to_back, and if it is true (1), set the flag - if (!strcmp(attr->_ident, "ins_avoid_back_to_back") != 0 && attr->int_val(*this) != 0) - avoid_back_to_back = true; - if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) - fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val); - + if (strcmp(attr->_ident, "ins_avoid_back_to_back") == 0) { + avoid_back_to_back_attr = attr; + } attr = (Attribute *)attr->_next; } @@ -1799,11 +1798,11 @@ } // flag: if this instruction should not be generated back to back. - if ( avoid_back_to_back ) { - if ( node_flags_set ) { - fprintf(fp," | Flag_avoid_back_to_back"); + if (avoid_back_to_back_attr != NULL) { + if (node_flags_set) { + fprintf(fp," | (%s)", avoid_back_to_back_attr->_val); } else { - fprintf(fp,"init_flags(Flag_avoid_back_to_back"); + fprintf(fp,"init_flags((%s)", avoid_back_to_back_attr->_val); node_flags_set = true; } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/asm/codeBuffer.cpp --- a/hotspot/src/share/vm/asm/codeBuffer.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -968,6 +968,7 @@ void CodeBuffer::log_section_sizes(const char* name) { if (xtty != NULL) { + ttyLocker ttyl; // log info about buffer usage xtty->print_cr("", name, _total_size); for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_Compilation.cpp --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -546,6 +546,7 @@ , _code(buffer_blob) , _has_access_indexed(false) , _current_instruction(NULL) +, _interpreter_frame_size(0) #ifndef PRODUCT , _last_instruction_printed(NULL) #endif // PRODUCT diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_Compilation.hpp --- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -88,6 +88,7 @@ CodeOffsets _offsets; CodeBuffer _code; bool _has_access_indexed; + int _interpreter_frame_size; // Stack space needed in case of a deoptimization // compilation helpers void initialize(); @@ -262,6 +263,18 @@ // Dump inlining replay data to the stream. void dump_inline_data(outputStream* out) { /* do nothing now */ } + + // How much stack space would the interpreter need in case of a + // deoptimization (worst case) + void update_interpreter_frame_size(int size) { + if (_interpreter_frame_size < size) { + _interpreter_frame_size = size; + } + } + + int interpreter_frame_size() const { + return _interpreter_frame_size; + } }; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_IR.cpp --- a/hotspot/src/share/vm/c1/c1_IR.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_IR.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -227,8 +227,38 @@ _oop_map->set_oop(name); } +// Mirror the stack size calculation in the deopt code +// How much stack space would we need at this point in the program in +// case of deoptimization? +int CodeEmitInfo::interpreter_frame_size() const { + ValueStack* state = _stack; + int size = 0; + int callee_parameters = 0; + int callee_locals = 0; + int extra_args = state->scope()->method()->max_stack() - state->stack_size(); + while (state != NULL) { + int locks = state->locks_size(); + int temps = state->stack_size(); + bool is_top_frame = (state == _stack); + ciMethod* method = state->scope()->method(); + int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(), + temps + callee_parameters, + extra_args, + locks, + callee_parameters, + callee_locals, + is_top_frame); + size += frame_size; + + callee_parameters = method->size_of_parameters(); + callee_locals = method->max_locals(); + extra_args = 0; + state = state->caller_state(); + } + return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord; +} // Implementation of IR diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_IR.hpp --- a/hotspot/src/share/vm/c1/c1_IR.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_IR.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -284,6 +284,8 @@ bool is_method_handle_invoke() const { return _is_method_handle_invoke; } void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } + + int interpreter_frame_size() const; }; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -190,6 +190,13 @@ return _masm->pc(); } +// To bang the stack of this compiled method we use the stack size +// that the interpreter would need in case of a deoptimization. This +// removes the need to bang the stack in the deoptimization blob which +// in turn simplifies stack overflow handling. +int LIR_Assembler::bang_size_in_bytes() const { + return MAX2(initial_frame_size_in_bytes(), _compilation->interpreter_frame_size()); +} void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) { for (int i = 0; i < info_list->length(); i++) { @@ -797,7 +804,7 @@ void LIR_Assembler::build_frame() { - _masm->build_frame(initial_frame_size_in_bytes()); + _masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_LIRAssembler.hpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -132,7 +132,8 @@ int code_offset() const; address pc() const; - int initial_frame_size_in_bytes(); + int initial_frame_size_in_bytes() const; + int bang_size_in_bytes() const; // test for constants which can be encoded directly in instructions static bool is_small_constant(LIR_Opr opr); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2451,6 +2451,9 @@ CodeEmitInfo* info = visitor.info_at(i); OopMap* oop_map = first_oop_map; + // compute worst case interpreter size in case of a deoptimization + _compilation->update_interpreter_frame_size(info->interpreter_frame_size()); + if (info->stack()->locks_size() != first_info->stack()->locks_size()) { // this info has a different number of locks then the precomputed oop map // (possible for lock and unlock instructions) -> compute oop map with diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/c1/c1_MacroAssembler.hpp --- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -39,7 +39,7 @@ void explicit_null_check(Register base); void inline_cache_check(Register receiver, Register iCache); - void build_frame(int frame_size_in_bytes); + void build_frame(int frame_size_in_bytes, int bang_size_in_bytes); void remove_frame(int frame_size_in_bytes); void unverified_entry(Register receiver, Register ic_klass); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciKlass.cpp --- a/hotspot/src/share/vm/ci/ciKlass.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciKlass.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -237,3 +237,9 @@ void ciKlass::print_name_on(outputStream* st) { name()->print_symbol_on(st); } + +const char* ciKlass::external_name() const { + GUARDED_VM_ENTRY( + return get_Klass()->external_name(); + ) +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciKlass.hpp --- a/hotspot/src/share/vm/ci/ciKlass.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciKlass.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -125,6 +125,8 @@ virtual ciKlass* exact_klass() = 0; void print_name_on(outputStream* st); + + const char* external_name() const; }; #endif // SHARE_VM_CI_CIKLASS_HPP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -80,6 +80,7 @@ _code_size = h_m()->code_size(); _intrinsic_id = h_m()->intrinsic_id(); _handler_count = h_m()->exception_table_length(); + _size_of_parameters = h_m()->size_of_parameters(); _uses_monitors = h_m()->access_flags().has_monitor_bytecodes(); _balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching(); _is_c1_compilable = !h_m()->is_not_c1_compilable(); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciMethod.hpp --- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -71,6 +71,7 @@ int _interpreter_invocation_count; int _interpreter_throwout_count; int _instructions_size; + int _size_of_parameters; bool _uses_monitors; bool _balanced_monitors; @@ -166,6 +167,7 @@ int exception_table_length() const { check_is_loaded(); return _handler_count; } int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; } int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; } + int size_of_parameters() const { check_is_loaded(); return _size_of_parameters; } // Code size for inlining decisions. int code_size_for_inlining(); @@ -241,7 +243,6 @@ ciField* get_field_at_bci( int bci, bool &will_link); ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature); - // Given a certain calling environment, find the monomorphic target // for the call. Return NULL if the call is not monomorphic in // its calling environment. diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciSymbol.cpp --- a/hotspot/src/share/vm/ci/ciSymbol.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciSymbol.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -123,6 +123,10 @@ GUARDED_VM_ENTRY(get_symbol()->print_symbol_on(st);) } +const char* ciSymbol::as_klass_external_name() const { + GUARDED_VM_ENTRY(return get_symbol()->as_klass_external_name();); +} + // ------------------------------------------------------------------ // ciSymbol::make_impl // diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/ci/ciSymbol.hpp --- a/hotspot/src/share/vm/ci/ciSymbol.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/ci/ciSymbol.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -90,6 +90,7 @@ void print_symbol() { print_symbol_on(tty); } + const char* as_klass_external_name() const; // Make a ciSymbol from a C string. // Consider adding to vmSymbols.hpp instead of using this constructor. diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2777,6 +2777,11 @@ "Short length on BootstrapMethods in class file %s", CHECK); + guarantee_property(attribute_byte_length > sizeof(u2), + "Invalid BootstrapMethods attribute length %u in class file %s", + attribute_byte_length, + CHECK); + // The attribute contains a counted array of counted tuples of shorts, // represending bootstrap specifiers: // length*{bootstrap_method_index, argument_count*{argument_index}} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/classfile/defaultMethods.cpp --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -390,20 +390,6 @@ Symbol* get_exception_message() { return _exception_message; } Symbol* get_exception_name() { return _exception_name; } - // Return true if the specified klass has a static method that matches - // the name and signature of the target method. - bool has_matching_static(InstanceKlass* root) { - if (_members.length() > 0) { - Pair entry = _members.at(0); - Method* impl = root->find_method(entry.first->name(), - entry.first->signature()); - if ((impl != NULL) && impl->is_static()) { - return true; - } - } - return false; - } - // Either sets the target or the exception error message void determine_target(InstanceKlass* root, TRAPS) { if (has_target() || throws_exception()) { @@ -433,21 +419,19 @@ // If the root klass has a static method with matching name and signature // then do not generate an overpass method because it will hide the // static method during resolution. - if (!has_matching_static(root)) { - if (qualified_methods.length() == 0) { - _exception_message = generate_no_defaults_message(CHECK); - } else { - assert(root != NULL, "Null root class"); - _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); - } - _exception_name = vmSymbols::java_lang_AbstractMethodError(); + if (qualified_methods.length() == 0) { + _exception_message = generate_no_defaults_message(CHECK); + } else { + assert(root != NULL, "Null root class"); + _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); } + _exception_name = vmSymbols::java_lang_AbstractMethodError(); // If only one qualified method is default, select that } else if (num_defaults == 1) { _selected_target = qualified_methods.at(default_index); - } else if (num_defaults > 1 && !has_matching_static(root)) { + } else if (num_defaults > 1) { _exception_message = generate_conflicts_message(&qualified_methods,CHECK); _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); if (TraceDefaultMethods) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/classfile/verificationType.hpp --- a/hotspot/src/share/vm/classfile/verificationType.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/classfile/verificationType.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ -299,7 +299,7 @@ int dimensions() const { assert(is_array(), "Must be an array"); int index = 0; - while (name()->byte_at(index++) == '['); + while (name()->byte_at(index) == '[') index++; return index; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, 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 @@ -1943,7 +1943,7 @@ InstanceKlass* target_instance = InstanceKlass::cast(target_class); fieldDescriptor fd; if (is_method) { - Method* m = target_instance->uncached_lookup_method(field_name, field_sig); + Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::normal); if (m != NULL && m->is_protected()) { if (!this_class->is_same_class_package(m->method_holder())) { return true; @@ -2280,7 +2280,8 @@ ref_class_type.name(), CHECK_VERIFY(this)); Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method( vmSymbols::object_initializer_name(), - cp->signature_ref_at(bcs->get_index_u2())); + cp->signature_ref_at(bcs->get_index_u2()), + Klass::normal); instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/compiler/compileLog.cpp --- a/hotspot/src/share/vm/compiler/compileLog.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/compiler/compileLog.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -106,7 +106,7 @@ if (mobj->is_klass()) { ciKlass* klass = mobj->as_klass(); begin_elem("klass id='%d'", id); - name(klass->name()); + name(klass); if (!klass->is_loaded()) { print(" unloaded='1'"); } else { @@ -171,6 +171,15 @@ print("'"); } +void CompileLog::name(ciKlass* k) { + print(" name='"); + if (!k->is_loaded()) { + text()->print(k->name()->as_klass_external_name()); + } else { + text()->print(k->external_name()); + } + print("'"); +} // ------------------------------------------------------------------ // CompileLog::clear_identities diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/compiler/compileLog.hpp --- a/hotspot/src/share/vm/compiler/compileLog.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/compiler/compileLog.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -28,6 +28,7 @@ #include "utilities/xmlstream.hpp" class ciBaseObject; +class ciKlass; class ciObject; class ciMetadata; class ciSymbol; @@ -72,6 +73,7 @@ void name(ciSymbol* s); // name='s' void name(Symbol* s) { xmlStream::name(s); } + void name(ciKlass* k); // Output an object description, return obj->ident(). int identify(ciBaseObject* obj); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -151,7 +151,7 @@ inline static void post_allocation_setup_no_klass_install(KlassHandle klass, HeapWord* objPtr); - inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj); + inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj, int size); inline static void post_allocation_setup_array(KlassHandle klass, HeapWord* obj, int length); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, 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 @@ -70,7 +70,7 @@ } // Support for jvmti and dtrace -inline void post_allocation_notify(KlassHandle klass, oop obj) { +inline void post_allocation_notify(KlassHandle klass, oop obj, int size) { // support low memory notifications (no-op if not enabled) LowMemoryDetector::detect_low_memory_for_collected_pools(); @@ -80,18 +80,19 @@ if (DTraceAllocProbes) { // support for Dtrace object alloc event (no-op most of the time) if (klass() != NULL && klass()->name() != NULL) { - SharedRuntime::dtrace_object_alloc(obj); + SharedRuntime::dtrace_object_alloc(obj, size); } } } void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, - HeapWord* obj) { + HeapWord* obj, + int size) { post_allocation_setup_common(klass, obj); assert(Universe::is_bootstrapping() || !((oop)obj)->is_array(), "must not be an array"); // notify jvmti and dtrace - post_allocation_notify(klass, (oop)obj); + post_allocation_notify(klass, (oop)obj, size); } void CollectedHeap::post_allocation_setup_array(KlassHandle klass, @@ -103,9 +104,10 @@ assert(length >= 0, "length should be non-negative"); ((arrayOop)obj)->set_length(length); post_allocation_setup_common(klass, obj); - assert(((oop)obj)->is_array(), "must be an array"); + oop new_obj = (oop)obj; + assert(new_obj->is_array(), "must be an array"); // notify jvmti and dtrace (must be after length is set for dtrace) - post_allocation_notify(klass, (oop)obj); + post_allocation_notify(klass, new_obj, new_obj->size()); } HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) { @@ -199,7 +201,7 @@ assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); - post_allocation_setup_obj(klass, obj); + post_allocation_setup_obj(klass, obj, size); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); return (oop)obj; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/interpreter/abstractInterpreter.hpp --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -181,30 +181,16 @@ // Deoptimization should reexecute this bytecode static bool bytecode_should_reexecute(Bytecodes::Code code); - // share implementation of size_activation and layout_activation: - static int size_activation(Method* method, + // deoptimization support + static int size_activation(int max_stack, int temps, - int popframe_args, + int extra_args, int monitors, - int caller_actual_parameters, int callee_params, int callee_locals, - bool is_top_frame, - bool is_bottom_frame) { - return layout_activation(method, - temps, - popframe_args, - monitors, - caller_actual_parameters, - callee_params, - callee_locals, - (frame*)NULL, - (frame*)NULL, - is_top_frame, - is_bottom_frame); - } + bool is_top_frame); - static int layout_activation(Method* method, + static void layout_activation(Method* method, int temps, int popframe_args, int monitors, diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -243,7 +243,8 @@ // Look up method in klasses, including static methods // Then look up local default methods void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature); + // Ignore overpasses so statics can be found during resolution + Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, @@ -256,6 +257,12 @@ result_oop = NULL; } + // Before considering default methods, check for an overpass in the + // current class if a method has not been found. + if (result_oop == NULL) { + result_oop = InstanceKlass::cast(klass())->find_method(name, signature); + } + if (result_oop == NULL) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { @@ -276,11 +283,11 @@ // returns first instance method // Looks up method in classes, then looks up local default methods void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature); + Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::normal); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) { KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super()); - result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature)); + result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); } if (result.is_null()) { @@ -302,7 +309,7 @@ // First check in default method array if (!resolved_method->is_abstract() && (InstanceKlass::cast(klass())->default_methods() != NULL)) { - int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature); + int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false); if (index >= 0 ) { vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); } @@ -322,7 +329,7 @@ // Specify 'true' in order to skip default methods when searching the // interfaces. Function lookup_method_in_klasses() already looked for // the method in the default methods table. - result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, true)); + result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults)); } void LinkResolver::lookup_polymorphic_method(methodHandle& result, diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/arrayKlass.cpp --- a/hotspot/src/share/vm/oops/arrayKlass.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -64,10 +64,10 @@ return NULL; } -Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); - return super()->uncached_lookup_method(name, signature); + return super()->uncached_lookup_method(name, signature, mode); } ArrayKlass::ArrayKlass(Symbol* name) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/arrayKlass.hpp --- a/hotspot/src/share/vm/oops/arrayKlass.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -86,7 +86,7 @@ objArrayOop allocate_arrayArray(int n, int length, TRAPS); // Lookup operations - Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // Casting from Klass* static ArrayKlass* cast(Klass* k) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1389,7 +1389,11 @@ // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { - return InstanceKlass::find_method(methods(), name, signature); + return find_method_impl(name, signature, false); +} + +Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { + return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass); } // find_instance_method looks up the name/signature in the local methods array @@ -1406,40 +1410,49 @@ // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array* methods, Symbol* name, Symbol* signature) { - int hit = find_method_index(methods, name, signature); + return InstanceKlass::find_method_impl(methods, name, signature, false); +} + +Method* InstanceKlass::find_method_impl( + Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { + int hit = find_method_index(methods, name, signature, skipping_overpass); return hit >= 0 ? methods->at(hit): NULL; } // Used directly for default_methods to find the index into the // default_vtable_indices, and indirectly by find_method // find_method_index looks in the local methods array to return the index -// of the matching name/signature +// of the matching name/signature. If, overpass methods are being ignored, +// the search continues to find a potential non-overpass match. This capability +// is important during method resolution to prefer a static method, for example, +// over an overpass method. int InstanceKlass::find_method_index( - Array* methods, Symbol* name, Symbol* signature) { + Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { int hit = binary_search(methods, name); if (hit != -1) { Method* m = methods->at(hit); // Do linear search to find matching signature. First, quick check - // for common case - if (m->signature() == signature) return hit; + // for common case, ignoring overpasses if requested. + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit; + // search downwards through overloaded methods int i; for (i = hit - 1; i >= 0; --i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return i; + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; } // search upwards for (i = hit + 1; i < methods->length(); ++i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return i; + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; } // not found #ifdef ASSERT - int index = linear_search(methods, name, signature); + int index = skipping_overpass ? -1 : linear_search(methods, name, signature); assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif } @@ -1465,16 +1478,16 @@ // uncached_lookup_method searches both the local class methods array and all // superclasses methods arrays, skipping any overpass methods in superclasses. -Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { + MethodLookupMode lookup_mode = mode; Klass* klass = const_cast(this); - bool dont_ignore_overpasses = true; // For the class being searched, find its overpasses. while (klass != NULL) { - Method* method = InstanceKlass::cast(klass)->find_method(name, signature); - if ((method != NULL) && (dont_ignore_overpasses || !method->is_overpass())) { + Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, (lookup_mode == skip_overpass)); + if (method != NULL) { return method; } klass = InstanceKlass::cast(klass)->super(); - dont_ignore_overpasses = false; // Ignore overpass methods in all superclasses. + lookup_mode = skip_overpass; // Always ignore overpass methods in superclasses } return NULL; } @@ -1489,7 +1502,7 @@ } // Look up interfaces if (m == NULL) { - m = lookup_method_in_all_interfaces(name, signature, false); + m = lookup_method_in_all_interfaces(name, signature, normal); } return m; } @@ -1499,7 +1512,7 @@ // They should only be found in the initial InterfaceMethodRef Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, - bool skip_default_methods) const { + MethodLookupMode mode) const { Array* all_ifs = transitive_interfaces(); int num_ifs = all_ifs->length(); InstanceKlass *ik = NULL; @@ -1507,7 +1520,7 @@ ik = InstanceKlass::cast(all_ifs->at(i)); Method* m = ik->lookup_method(name, signature); if (m != NULL && m->is_public() && !m->is_static() && - (!skip_default_methods || !m->is_default_method())) { + ((mode != skip_defaults) || !m->is_default_method())) { return m; } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -490,14 +490,14 @@ static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); // find a local method index in default_methods (returns -1 if not found) - static int find_method_index(Array* methods, Symbol* name, Symbol* signature); + static int find_method_index(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); // lookup operation (returns NULL if not found) - Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // lookup a method in all the interfaces that this class implements // (returns NULL if not found) - Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, bool skip_default_methods) const; + Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // lookup a method in local defaults then in all interfaces // (returns NULL if not found) @@ -1020,6 +1020,10 @@ // Returns the array class with this class as element type Klass* array_klass_impl(bool or_null, TRAPS); + // find a local method (returns NULL if not found) + Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const; + static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); + // Free CHeap allocated fields. void release_C_heap_structures(); public: diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/klass.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -129,7 +129,7 @@ } -Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { #ifdef ASSERT tty->print_cr("Error: uncached_lookup_method called on a klass oop." " Likely error: reflection method does not correctly" diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/klass.hpp --- a/hotspot/src/share/vm/oops/klass.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/klass.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -154,6 +154,8 @@ void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); public: + enum MethodLookupMode { normal, skip_overpass, skip_defaults }; + bool is_klass() const volatile { return true; } // super @@ -391,10 +393,10 @@ virtual void initialize(TRAPS); // lookup operation for MethodLookupCache friend class MethodLookupCache; - virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const { - return uncached_lookup_method(name, signature); + return uncached_lookup_method(name, signature, normal); } // array class with specific rank diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/klassVtable.cpp --- a/hotspot/src/share/vm/oops/klassVtable.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/klassVtable.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -622,7 +622,7 @@ // this check for all access permissions. InstanceKlass *sk = InstanceKlass::cast(super); if (sk->has_miranda_methods()) { - if (sk->lookup_method_in_all_interfaces(name, signature, false) != NULL) { + if (sk->lookup_method_in_all_interfaces(name, signature, Klass::normal) != NULL) { return false; // found a matching miranda; we do not need a new entry } } @@ -698,7 +698,7 @@ && mo->method_holder() != NULL && mo->method_holder()->super() != NULL) { - mo = mo->method_holder()->super()->uncached_lookup_method(name, signature); + mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::normal); } if (mo == NULL || mo->access_flags().is_private() ) { // super class hierarchy does not implement it or protection is different @@ -743,7 +743,7 @@ if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all? InstanceKlass *sk = InstanceKlass::cast(super); // check if it is a duplicate of a super's miranda - if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), false) == NULL) { + if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::normal) == NULL) { new_mirandas->append(im); } if (all_mirandas != NULL) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/oops/objArrayKlass.cpp --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -269,7 +269,7 @@ if (element_is_null || (new_val->klass())->is_subtype_of(bound)) { bs->write_ref_field_pre(p, new_val); - *p = *from; + *p = element; } else { // We must do a barrier to cover the partial copy. const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -266,14 +266,17 @@ // Allow inlining decisions to be delayed class LateInlineCallGenerator : public DirectCallGenerator { + private: + // unique id for log compilation + jlong _unique_id; + protected: CallGenerator* _inline_cg; - virtual bool do_late_inline_check(JVMState* jvms) { return true; } public: LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : - DirectCallGenerator(method, true), _inline_cg(inline_cg) {} + DirectCallGenerator(method, true), _inline_cg(inline_cg), _unique_id(0) {} virtual bool is_late_inline() const { return true; } @@ -283,6 +286,8 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); + C->log_inline_id(this); + // Record that this call site should be revisited once the main // parse is finished. if (!is_mh_late_inline()) { @@ -304,6 +309,14 @@ C->print_inlining_move_to(this); C->print_inlining_update_delayed(this); } + + virtual void set_unique_id(jlong id) { + _unique_id = id; + } + + virtual jlong unique_id() const { + return _unique_id; + } }; void LateInlineCallGenerator::do_late_inline() { @@ -368,6 +381,8 @@ C->print_inlining_move_to(this); + C->log_late_inline(this); + // This check is done here because for_method_handle_inline() method // needs jvms for inlined state. if (!do_late_inline_check(jvms)) { @@ -375,17 +390,6 @@ return; } - CompileLog* log = C->log(); - if (log != NULL) { - log->head("late_inline method='%d'", log->identify(method())); - JVMState* p = jvms; - while (p != NULL) { - log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); - p = p->caller(); - } - log->tail("late_inline"); - } - // Setup default node notes to be picked up by the inlining Node_Notes* old_nn = C->default_node_notes(); if (old_nn != NULL) { @@ -438,11 +442,12 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser); + Compile* C = Compile::current(); if (_input_not_const) { // inlining won't be possible so no need to enqueue right now. call_node()->set_generator(this); } else { - Compile::current()->add_late_inline(this); + C->add_late_inline(this); } return new_jvms; } @@ -483,6 +488,9 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); + + C->log_inline_id(this); + C->add_string_late_inline(this); JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); @@ -505,6 +513,8 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); + C->log_inline_id(this); + C->add_boxing_late_inline(this); JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); @@ -786,6 +796,7 @@ } else { const char* msg = "receiver not constant"; if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); + C->log_inline_failure(msg); } } break; @@ -858,6 +869,7 @@ } else { const char* msg = "member_name not constant"; if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); + C->log_inline_failure(msg); } } break; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/callGenerator.hpp --- a/hotspot/src/share/vm/opto/callGenerator.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/callGenerator.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -84,6 +84,9 @@ virtual CallStaticJavaNode* call_node() const { ShouldNotReachHere(); return NULL; } + virtual void set_unique_id(jlong id) { fatal("unique id only for late inlines"); }; + virtual jlong unique_id() const { fatal("unique id only for late inlines"); return 0; }; + // Note: It is possible for a CG to be both inline and virtual. // (The hashCode intrinsic does a vtable check and an inlined fast path.) diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/callnode.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -608,6 +608,39 @@ } } +// Mirror the stack size calculation in the deopt code +// How much stack space would we need at this point in the program in +// case of deoptimization? +int JVMState::interpreter_frame_size() const { + const JVMState* jvms = this; + int size = 0; + int callee_parameters = 0; + int callee_locals = 0; + int extra_args = method()->max_stack() - stk_size(); + + while (jvms != NULL) { + int locks = jvms->nof_monitors(); + int temps = jvms->stk_size(); + bool is_top_frame = (jvms == this); + ciMethod* method = jvms->method(); + + int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(), + temps + callee_parameters, + extra_args, + locks, + callee_parameters, + callee_locals, + is_top_frame); + size += frame_size; + + callee_parameters = method->size_of_parameters(); + callee_locals = method->max_locals(); + extra_args = 0; + jvms = jvms->caller(); + } + return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord; +} + //============================================================================= uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/callnode.hpp --- a/hotspot/src/share/vm/opto/callnode.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/callnode.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -300,6 +300,7 @@ JVMState* clone_shallow(Compile* C) const; // retains uncloned caller void set_map_deep(SafePointNode *map);// reset map for all callers void adapt_position(int delta); // Adapt offsets in in-array after adding an edge. + int interpreter_frame_size() const; #ifndef PRODUCT void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -440,6 +440,14 @@ return words; } +// To bang the stack of this compiled method we use the stack size +// that the interpreter would need in case of a deoptimization. This +// removes the need to bang the stack in the deoptimization blob which +// in turn simplifies stack overflow handling. +int Compile::bang_size_in_bytes() const { + return MAX2(_interpreter_frame_size, frame_size_in_bytes()); +} + // ============================================================================ //------------------------------CompileWrapper--------------------------------- class CompileWrapper : public StackObj { @@ -664,7 +672,8 @@ _print_inlining_list(NULL), _print_inlining_stream(NULL), _print_inlining_idx(0), - _preserve_jvm_state(0) { + _preserve_jvm_state(0), + _interpreter_frame_size(0) { C = this; CompileWrapper cw(this); @@ -969,7 +978,8 @@ _print_inlining_stream(NULL), _print_inlining_idx(0), _preserve_jvm_state(0), - _allowed_reasons(0) { + _allowed_reasons(0), + _interpreter_frame_size(0) { C = this; #ifndef PRODUCT @@ -3078,8 +3088,12 @@ Node* m = n->in(i); ++i; if (m != NULL && !frc._visited.test_set(m->_idx)) { - if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL) + if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL) { + // compute worst case interpreter size in case of a deoptimization + update_interpreter_frame_size(m->as_SafePoint()->jvms()->interpreter_frame_size()); + sfpt.push(m); + } cnt = m->req(); nstack.push(n, i); // put on stack parent and next input's index n = m; @@ -3851,7 +3865,7 @@ void Compile::dump_inlining() { bool do_print_inlining = print_inlining() || print_intrinsics(); - if (do_print_inlining) { + if (do_print_inlining || log() != NULL) { // Print inlining message for candidates that we couldn't inline // for lack of space for (int i = 0; i < _late_inlines.length(); i++) { @@ -3861,6 +3875,7 @@ if (do_print_inlining) { cg->print_inlining_late(msg); } + log_late_inline_failure(cg, msg); } } } @@ -3871,6 +3886,48 @@ } } +void Compile::log_late_inline(CallGenerator* cg) { + if (log() != NULL) { + log()->head("late_inline method='%d' inline_id='" JLONG_FORMAT "'", log()->identify(cg->method()), + cg->unique_id()); + JVMState* p = cg->call_node()->jvms(); + while (p != NULL) { + log()->elem("jvms bci='%d' method='%d'", p->bci(), log()->identify(p->method())); + p = p->caller(); + } + log()->tail("late_inline"); + } +} + +void Compile::log_late_inline_failure(CallGenerator* cg, const char* msg) { + log_late_inline(cg); + if (log() != NULL) { + log()->inline_fail(msg); + } +} + +void Compile::log_inline_id(CallGenerator* cg) { + if (log() != NULL) { + // The LogCompilation tool needs a unique way to identify late + // inline call sites. This id must be unique for this call site in + // this compilation. Try to have it unique across compilations as + // well because it can be convenient when grepping through the log + // file. + // Distinguish OSR compilations from others in case CICountOSR is + // on. + jlong id = ((jlong)unique()) + (((jlong)compile_id()) << 33) + (CICountOSR && is_osr_compilation() ? ((jlong)1) << 32 : 0); + cg->set_unique_id(id); + log()->elem("inline_id id='" JLONG_FORMAT "'", id); + } +} + +void Compile::log_inline_failure(const char* msg) { + if (C->log() != NULL) { + C->log()->inline_fail(msg); + } +} + + // Dump inlining replay data to the stream. // Don't change thread state and acquire any locks. void Compile::dump_inline_data(outputStream* out) { @@ -4048,8 +4105,8 @@ worklist.push(root()); for (uint next = 0; next < worklist.size(); ++next) { Node *n = worklist.at(next); - const Type* t = igvn.type(n); - assert(t == t->remove_speculative(), "no more speculative types"); + const Type* t = igvn.type_or_null(n); + assert((t == NULL) || (t == t->remove_speculative()), "no more speculative types"); if (n->is_Type()) { t = n->as_Type()->type(); assert(t == t->remove_speculative(), "no more speculative types"); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/compile.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -440,6 +440,8 @@ void print_inlining_push(); PrintInliningBuffer& print_inlining_current(); + void log_late_inline_failure(CallGenerator* cg, const char* msg); + public: outputStream* print_inlining_stream() const { @@ -459,6 +461,10 @@ print_inlining_stream()->print(ss.as_string()); } + void log_late_inline(CallGenerator* cg); + void log_inline_id(CallGenerator* cg); + void log_inline_failure(const char* msg); + void* replay_inline_data() const { return _replay_inline_data; } // Dump inlining replay data to the stream. @@ -478,6 +484,7 @@ RegMask _FIRST_STACK_mask; // All stack slots usable for spills (depends on frame layout) Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin void* _indexSet_free_block_list; // free list of IndexSet bit blocks + int _interpreter_frame_size; uint _node_bundling_limit; Bundle* _node_bundling_base; // Information for instruction bundling @@ -935,6 +942,7 @@ PhaseRegAlloc* regalloc() { return _regalloc; } int frame_slots() const { return _frame_slots; } int frame_size_in_words() const; // frame_slots in units of the polymorphic 'words' + int frame_size_in_bytes() const { return _frame_slots << LogBytesPerInt; } RegMask& FIRST_STACK_mask() { return _FIRST_STACK_mask; } Arena* indexSet_arena() { return _indexSet_arena; } void* indexSet_free_block_list() { return _indexSet_free_block_list; } @@ -946,6 +954,13 @@ bool need_stack_bang(int frame_size_in_bytes) const; bool need_register_stack_bang() const; + void update_interpreter_frame_size(int size) { + if (_interpreter_frame_size < size) { + _interpreter_frame_size = size; + } + } + int bang_size_in_bytes() const; + void set_matcher(Matcher* m) { _matcher = m; } //void set_regalloc(PhaseRegAlloc* ra) { _regalloc = ra; } void set_indexSet_arena(Arena* a) { _indexSet_arena = a; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/doCall.cpp --- a/hotspot/src/share/vm/opto/doCall.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -104,6 +104,9 @@ log->print(" receiver2='%d' receiver2_count='%d'", r2id, profile.receiver_count(1)); } } + if (callee->is_method_handle_intrinsic()) { + log->print(" method_handle_intrinsic='1'"); + } log->end_elem(); } @@ -296,6 +299,7 @@ if (call_does_dispatch) { const char* msg = "virtual call"; if (PrintInlining) print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); + C->log_inline_failure(msg); return CallGenerator::for_virtual_call(callee, vtable_index); } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -711,7 +711,7 @@ Node *val = n->in(MemNode::ValueIn); PointsToNode* ptn = ptnode_adr(val->_idx); assert(ptn != NULL, "node should be registered"); - ptn->set_escape_state(PointsToNode::GlobalEscape); + set_escape_state(ptn, PointsToNode::GlobalEscape); // Add edge to object for unsafe access with offset. PointsToNode* adr_ptn = ptnode_adr(adr->_idx); assert(adr_ptn != NULL, "node should be registered"); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1150,6 +1150,7 @@ // Now force out all loop-invariant dominating tests. The optimizer // finds some, but we _know_ they are all useless. peeled_dom_test_elim(loop,old_new); + loop->record_for_igvn(); } //------------------------------is_invariant----------------------------- diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -3172,17 +3172,16 @@ bool had_error = false; #ifdef ASSERT if (early != C->root()) { - // Make sure that there's a dominance path from use to LCA - Node* d = use; - while (d != LCA) { - d = idom(d); + // Make sure that there's a dominance path from LCA to early + Node* d = LCA; + while (d != early) { if (d == C->root()) { - tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx); - n->dump(); - use->dump(); + dump_bad_graph("Bad graph detected in compute_lca_of_uses", n, early, LCA); + tty->print_cr("*** Use %d isn't dominated by def %d ***", use->_idx, n->_idx); had_error = true; break; } + d = idom(d); } } #endif @@ -3435,6 +3434,13 @@ _igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops. } +#ifdef ASSERT + if (_verify_only && !n->is_CFG()) { + // Check def-use domination. + compute_lca_of_uses(n, get_ctrl(n), true /* verify */); + } +#endif + // CFG and pinned nodes already handled if( n->in(0) ) { if( n->in(0)->is_top() ) return; // Dead? diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2700,6 +2700,7 @@ // Inhibit more partial peeling on this loop new_head_clone->set_partial_peel_loop(); C->set_major_progress(); + loop->record_for_igvn(); #if !defined(PRODUCT) if (TracePartialPeeling) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/machnode.hpp --- a/hotspot/src/share/vm/opto/machnode.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/machnode.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -210,7 +210,14 @@ bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; } // Avoid back to back some instructions on some CPUs. - bool avoid_back_to_back() const { return (flags() & Flag_avoid_back_to_back) != 0; } + enum AvoidBackToBackFlag { AVOID_NONE = 0, + AVOID_BEFORE = Flag_avoid_back_to_back_before, + AVOID_AFTER = Flag_avoid_back_to_back_after, + AVOID_BEFORE_AND_AFTER = AVOID_BEFORE | AVOID_AFTER }; + + bool avoid_back_to_back(AvoidBackToBackFlag flag_value) const { + return (flags() & flag_value) == flag_value; + } // instruction implemented with a call bool has_call() const { return (flags() & Flag_has_call) != 0; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/node.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -645,17 +645,18 @@ // Flags are sorted by usage frequency. enum NodeFlags { - Flag_is_Copy = 0x01, // should be first bit to avoid shift - Flag_rematerialize = Flag_is_Copy << 1, + Flag_is_Copy = 0x01, // should be first bit to avoid shift + Flag_rematerialize = Flag_is_Copy << 1, Flag_needs_anti_dependence_check = Flag_rematerialize << 1, - Flag_is_macro = Flag_needs_anti_dependence_check << 1, - Flag_is_Con = Flag_is_macro << 1, - Flag_is_cisc_alternate = Flag_is_Con << 1, - Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, - Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, - Flag_avoid_back_to_back = Flag_may_be_short_branch << 1, - Flag_has_call = Flag_avoid_back_to_back << 1, - Flag_is_expensive = Flag_has_call << 1, + Flag_is_macro = Flag_needs_anti_dependence_check << 1, + Flag_is_Con = Flag_is_macro << 1, + Flag_is_cisc_alternate = Flag_is_Con << 1, + Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, + Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, + Flag_avoid_back_to_back_before = Flag_may_be_short_branch << 1, + Flag_avoid_back_to_back_after = Flag_avoid_back_to_back_before << 1, + Flag_has_call = Flag_avoid_back_to_back_after << 1, + Flag_is_expensive = Flag_has_call << 1, _max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination }; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/output.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -165,8 +165,13 @@ // Determine if we need to generate a stack overflow check. // Do it if the method is not a stub function and // has java calls or has frame size > vm_page_size/8. + // The debug VM checks that deoptimization doesn't trigger an + // unexpected stack overflow (compiled method stack banging should + // guarantee it doesn't happen) so we always need the stack bang in + // a debug VM. return (UseStackBanging && stub_function() == NULL && - (has_java_calls() || frame_size_in_bytes > os::vm_page_size()>>3)); + (has_java_calls() || frame_size_in_bytes > os::vm_page_size()>>3 + DEBUG_ONLY(|| true))); } bool Compile::need_register_stack_bang() const { @@ -411,7 +416,7 @@ blk_size += nop_size; } } - if (mach->avoid_back_to_back()) { + if (mach->avoid_back_to_back(MachNode::AVOID_BEFORE)) { // Nop is inserted between "avoid back to back" instructions. // ScheduleAndBundle() can rearrange nodes in a block, // check for all offsets inside this block. @@ -439,7 +444,7 @@ last_call_adr = blk_starts[i]+blk_size; } // Remember end of avoid_back_to_back offset - if (nj->is_Mach() && nj->as_Mach()->avoid_back_to_back()) { + if (nj->is_Mach() && nj->as_Mach()->avoid_back_to_back(MachNode::AVOID_AFTER)) { last_avoid_back_to_back_adr = blk_starts[i]+blk_size; } } @@ -525,11 +530,11 @@ int new_size = replacement->size(_regalloc); int diff = br_size - new_size; assert(diff >= (int)nop_size, "short_branch size should be smaller"); - // Conservatively take into accound padding between + // Conservatively take into account padding between // avoid_back_to_back branches. Previous branch could be // converted into avoid_back_to_back branch during next // rounds. - if (needs_padding && replacement->avoid_back_to_back()) { + if (needs_padding && replacement->avoid_back_to_back(MachNode::AVOID_BEFORE)) { jmp_offset[i] += nop_size; diff -= nop_size; } @@ -548,7 +553,7 @@ } } // (mach->may_be_short_branch()) if (mach != NULL && (mach->may_be_short_branch() || - mach->avoid_back_to_back())) { + mach->avoid_back_to_back(MachNode::AVOID_AFTER))) { last_may_be_short_branch_adr = blk_starts[i] + jmp_offset[i] + jmp_size[i]; } blk_starts[i+1] -= adjust_block_start; @@ -1313,7 +1318,7 @@ if (is_sfn && !is_mcall && padding == 0 && current_offset == last_call_offset) { padding = nop_size; } - if (padding == 0 && mach->avoid_back_to_back() && + if (padding == 0 && mach->avoid_back_to_back(MachNode::AVOID_BEFORE) && current_offset == last_avoid_back_to_back_offset) { // Avoid back to back some instructions. padding = nop_size; @@ -1407,7 +1412,7 @@ int new_size = replacement->size(_regalloc); assert((br_size - new_size) >= (int)nop_size, "short_branch size should be smaller"); // Insert padding between avoid_back_to_back branches. - if (needs_padding && replacement->avoid_back_to_back()) { + if (needs_padding && replacement->avoid_back_to_back(MachNode::AVOID_BEFORE)) { MachNode *nop = new (this) MachNopNode(); block->insert_node(nop, j++); _cfg->map_node_to_block(nop, block); @@ -1515,7 +1520,7 @@ last_call_offset = current_offset; } - if (n->is_Mach() && n->as_Mach()->avoid_back_to_back()) { + if (n->is_Mach() && n->as_Mach()->avoid_back_to_back(MachNode::AVOID_AFTER)) { // Avoid back to back some instructions. last_avoid_back_to_back_offset = current_offset; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/phaseX.cpp --- a/hotspot/src/share/vm/opto/phaseX.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -831,154 +831,111 @@ } } +/** + * Initialize worklist for each node. + */ +void PhaseIterGVN::init_worklist(Node* first) { + Unique_Node_List to_process; + to_process.push(first); + + while (to_process.size() > 0) { + Node* n = to_process.pop(); + if (!_worklist.member(n)) { + _worklist.push(n); + + uint cnt = n->req(); + for(uint i = 0; i < cnt; i++) { + Node* m = n->in(i); + if (m != NULL) { + to_process.push(m); + } + } + } + } +} #ifndef PRODUCT void PhaseIterGVN::verify_step(Node* n) { - _verify_window[_verify_counter % _verify_window_size] = n; - ++_verify_counter; - ResourceMark rm; - ResourceArea *area = Thread::current()->resource_area(); - VectorSet old_space(area), new_space(area); - if (C->unique() < 1000 || - 0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) { - ++_verify_full_passes; - Node::verify_recur(C->root(), -1, old_space, new_space); - } - const int verify_depth = 4; - for ( int i = 0; i < _verify_window_size; i++ ) { - Node* n = _verify_window[i]; - if ( n == NULL ) continue; - if( n->in(0) == NodeSentinel ) { // xform_idom - _verify_window[i] = n->in(1); - --i; continue; + if (VerifyIterativeGVN) { + _verify_window[_verify_counter % _verify_window_size] = n; + ++_verify_counter; + ResourceMark rm; + ResourceArea* area = Thread::current()->resource_area(); + VectorSet old_space(area), new_space(area); + if (C->unique() < 1000 || + 0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) { + ++_verify_full_passes; + Node::verify_recur(C->root(), -1, old_space, new_space); } - // Typical fanout is 1-2, so this call visits about 6 nodes. - Node::verify_recur(n, verify_depth, old_space, new_space); - } -} -#endif - - -//------------------------------init_worklist---------------------------------- -// Initialize worklist for each node. -void PhaseIterGVN::init_worklist( Node *n ) { - if( _worklist.member(n) ) return; - _worklist.push(n); - uint cnt = n->req(); - for( uint i =0 ; i < cnt; i++ ) { - Node *m = n->in(i); - if( m ) init_worklist(m); + const int verify_depth = 4; + for ( int i = 0; i < _verify_window_size; i++ ) { + Node* n = _verify_window[i]; + if ( n == NULL ) continue; + if( n->in(0) == NodeSentinel ) { // xform_idom + _verify_window[i] = n->in(1); + --i; continue; + } + // Typical fanout is 1-2, so this call visits about 6 nodes. + Node::verify_recur(n, verify_depth, old_space, new_space); + } } } -//------------------------------optimize--------------------------------------- -void PhaseIterGVN::optimize() { - debug_only(uint num_processed = 0;); -#ifndef PRODUCT - { - _verify_counter = 0; - _verify_full_passes = 0; - for ( int i = 0; i < _verify_window_size; i++ ) { - _verify_window[i] = NULL; +void PhaseIterGVN::trace_PhaseIterGVN(Node* n, Node* nn, const Type* oldtype) { + if (TraceIterativeGVN) { + uint wlsize = _worklist.size(); + const Type* newtype = type_or_null(n); + if (nn != n) { + // print old node + tty->print("< "); + if (oldtype != newtype && oldtype != NULL) { + oldtype->dump(); + } + do { tty->print("\t"); } while (tty->position() < 16); + tty->print("<"); + n->dump(); + } + if (oldtype != newtype || nn != n) { + // print new node and/or new type + if (oldtype == NULL) { + tty->print("* "); + } else if (nn != n) { + tty->print("> "); + } else { + tty->print("= "); + } + if (newtype == NULL) { + tty->print("null"); + } else { + newtype->dump(); + } + do { tty->print("\t"); } while (tty->position() < 16); + nn->dump(); + } + if (Verbose && wlsize < _worklist.size()) { + tty->print(" Push {"); + while (wlsize != _worklist.size()) { + Node* pushed = _worklist.at(wlsize++); + tty->print(" %d", pushed->_idx); + } + tty->print_cr(" }"); + } + if (nn != n) { + // ignore n, it might be subsumed + verify_step((Node*) NULL); } } -#endif - -#ifdef ASSERT - Node* prev = NULL; - uint rep_cnt = 0; -#endif - uint loop_count = 0; - - // Pull from worklist; transform node; - // If node has changed: update edge info and put uses on worklist. - while( _worklist.size() ) { - if (C->check_node_count(NodeLimitFudgeFactor * 2, - "out of nodes optimizing method")) { - return; - } - Node *n = _worklist.pop(); - if (++loop_count >= K * C->live_nodes()) { - debug_only(n->dump(4);) - assert(false, "infinite loop in PhaseIterGVN::optimize"); - C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); - return; - } -#ifdef ASSERT - if (n == prev) { - if (++rep_cnt > 3) { - n->dump(4); - assert(false, "loop in Ideal transformation"); - } - } else { - rep_cnt = 0; - } - prev = n; -#endif - if (TraceIterativeGVN && Verbose) { - tty->print(" Pop "); - NOT_PRODUCT( n->dump(); ) - debug_only(if( (num_processed++ % 100) == 0 ) _worklist.print_set();) - } - - if (n->outcnt() != 0) { - -#ifndef PRODUCT - uint wlsize = _worklist.size(); - const Type* oldtype = type_or_null(n); -#endif //PRODUCT - - Node *nn = transform_old(n); +} -#ifndef PRODUCT - if (TraceIterativeGVN) { - const Type* newtype = type_or_null(n); - if (nn != n) { - // print old node - tty->print("< "); - if (oldtype != newtype && oldtype != NULL) { - oldtype->dump(); - } - do { tty->print("\t"); } while (tty->position() < 16); - tty->print("<"); - n->dump(); - } - if (oldtype != newtype || nn != n) { - // print new node and/or new type - if (oldtype == NULL) { - tty->print("* "); - } else if (nn != n) { - tty->print("> "); - } else { - tty->print("= "); - } - if (newtype == NULL) { - tty->print("null"); - } else { - newtype->dump(); - } - do { tty->print("\t"); } while (tty->position() < 16); - nn->dump(); - } - if (Verbose && wlsize < _worklist.size()) { - tty->print(" Push {"); - while (wlsize != _worklist.size()) { - Node* pushed = _worklist.at(wlsize++); - tty->print(" %d", pushed->_idx); - } - tty->print_cr(" }"); - } - } - if( VerifyIterativeGVN && nn != n ) { - verify_step((Node*) NULL); // ignore n, it might be subsumed - } -#endif - } else if (!n->is_top()) { - remove_dead_node(n); - } +void PhaseIterGVN::init_verifyPhaseIterGVN() { + _verify_counter = 0; + _verify_full_passes = 0; + for (int i = 0; i < _verify_window_size; i++) { + _verify_window[i] = NULL; } +} -#ifndef PRODUCT +void PhaseIterGVN::verify_PhaseIterGVN() { C->verify_graph_edges(); if( VerifyOpto && allow_progress() ) { // Must turn off allow_progress to enable assert and break recursion @@ -998,21 +955,78 @@ igvn2.set_allow_progress(true); } } - if ( VerifyIterativeGVN && PrintOpto ) { - if ( _verify_counter == _verify_full_passes ) + if (VerifyIterativeGVN && PrintOpto) { + if (_verify_counter == _verify_full_passes) { tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes", _verify_full_passes); - else + } else { tty->print_cr("VerifyIterativeGVN: %d transforms, %d full verify passes", _verify_counter, _verify_full_passes); + } } -#endif +} +#endif /* PRODUCT */ + +#ifdef ASSERT +/** + * Dumps information that can help to debug the problem. A debug + * build fails with an assert. + */ +void PhaseIterGVN::dump_infinite_loop_info(Node* n) { + n->dump(4); + _worklist.dump(); + assert(false, "infinite loop in PhaseIterGVN::optimize"); +} + +/** + * Prints out information about IGVN if the 'verbose' option is used. + */ +void PhaseIterGVN::trace_PhaseIterGVN_verbose(Node* n, int num_processed) { + if (TraceIterativeGVN && Verbose) { + tty->print(" Pop "); + n->dump(); + if ((num_processed % 100) == 0) { + _worklist.print_set(); + } + } +} +#endif /* ASSERT */ + +void PhaseIterGVN::optimize() { + DEBUG_ONLY(uint num_processed = 0;) + NOT_PRODUCT(init_verifyPhaseIterGVN();) + + uint loop_count = 0; + // Pull from worklist and transform the node. If the node has changed, + // update edge info and put uses on worklist. + while(_worklist.size()) { + if (C->check_node_count(NodeLimitFudgeFactor * 2, "Out of nodes")) { + return; + } + Node* n = _worklist.pop(); + if (++loop_count >= K * C->live_nodes()) { + DEBUG_ONLY(dump_infinite_loop_info(n);) + C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); + return; + } + DEBUG_ONLY(trace_PhaseIterGVN_verbose(n, num_processed++);) + if (n->outcnt() != 0) { + NOT_PRODUCT(const Type* oldtype = type_or_null(n)); + // Do the transformation + Node* nn = transform_old(n); + NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);) + } else if (!n->is_top()) { + remove_dead_node(n); + } + } + NOT_PRODUCT(verify_PhaseIterGVN();) } -//------------------register_new_node_with_optimizer--------------------------- -// Register a new node with the optimizer. Update the types array, the def-use -// info. Put on worklist. +/** + * Register a new node with the optimizer. Update the types array, the def-use + * info. Put on worklist. + */ Node* PhaseIterGVN::register_new_node_with_optimizer(Node* n, Node* orig) { set_type_bottom(n); _worklist.push(n); @@ -1038,32 +1052,29 @@ return transform_old(n); } -//------------------------------transform_old---------------------------------- -Node *PhaseIterGVN::transform_old( Node *n ) { -#ifndef PRODUCT - debug_only(uint loop_count = 0;); - set_transforms(); -#endif +Node *PhaseIterGVN::transform_old(Node* n) { + DEBUG_ONLY(uint loop_count = 0;); + NOT_PRODUCT(set_transforms()); + // Remove 'n' from hash table in case it gets modified _table.hash_delete(n); - if( VerifyIterativeGVN ) { - assert( !_table.find_index(n->_idx), "found duplicate entry in table"); + if (VerifyIterativeGVN) { + assert(!_table.find_index(n->_idx), "found duplicate entry in table"); } // Apply the Ideal call in a loop until it no longer applies - Node *k = n; + Node* k = n; DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) - Node *i = k->Ideal(this, /*can_reshape=*/true); + Node* i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT - if( VerifyIterativeGVN ) - verify_step(k); - if( i && VerifyOpto ) { - if( !allow_progress() ) { - if (i->is_Add() && i->outcnt() == 1) { + verify_step(k); + if (i && VerifyOpto ) { + if (!allow_progress()) { + if (i->is_Add() && (i->outcnt() == 1)) { // Switched input to left side because this is the only use - } else if( i->is_If() && (i->in(0) == NULL) ) { + } else if (i->is_If() && (i->in(0) == NULL)) { // This IF is dead because it is dominated by an equivalent IF When // dominating if changed, info is not propagated sparsely to 'this' // Propagating this info further will spuriously identify other @@ -1071,35 +1082,38 @@ return i; } else set_progress(); - } else + } else { set_progress(); + } } #endif - while( i ) { + while (i != NULL) { #ifndef PRODUCT - debug_only( if( loop_count >= K ) i->dump(4); ) - assert(loop_count < K, "infinite loop in PhaseIterGVN::transform"); - debug_only( loop_count++; ) + if (loop_count >= K) { + dump_infinite_loop_info(i); + } + loop_count++; #endif assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes"); // Made a change; put users of original Node on worklist - add_users_to_worklist( k ); + add_users_to_worklist(k); // Replacing root of transform tree? - if( k != i ) { + if (k != i) { // Make users of old Node now use new. - subsume_node( k, i ); + subsume_node(k, i); k = i; } DEBUG_ONLY(dead_loop_check(k);) // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) i = k->Ideal(this, /*can_reshape=*/true); - assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); + assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); #ifndef PRODUCT - if( VerifyIterativeGVN ) - verify_step(k); - if( i && VerifyOpto ) set_progress(); + verify_step(k); + if (i && VerifyOpto) { + set_progress(); + } #endif } @@ -1107,48 +1121,49 @@ ensure_type_or_null(k); // See what kind of values 'k' takes on at runtime - const Type *t = k->Value(this); + const Type* t = k->Value(this); assert(t != NULL, "value sanity"); // Since I just called 'Value' to compute the set of run-time values // for this Node, and 'Value' is non-local (and therefore expensive) I'll // cache Value. Later requests for the local phase->type of this Node can // use the cached Value instead of suffering with 'bottom_type'. - if (t != type_or_null(k)) { - NOT_PRODUCT( set_progress(); ) - NOT_PRODUCT( inc_new_values();) + if (type_or_null(k) != t) { +#ifndef PRODUCT + inc_new_values(); + set_progress(); +#endif set_type(k, t); // If k is a TypeNode, capture any more-precise type permanently into Node k->raise_bottom_type(t); // Move users of node to worklist - add_users_to_worklist( k ); + add_users_to_worklist(k); } - // If 'k' computes a constant, replace it with a constant - if( t->singleton() && !k->is_Con() ) { - NOT_PRODUCT( set_progress(); ) - Node *con = makecon(t); // Make a constant - add_users_to_worklist( k ); - subsume_node( k, con ); // Everybody using k now uses con + if (t->singleton() && !k->is_Con()) { + NOT_PRODUCT(set_progress();) + Node* con = makecon(t); // Make a constant + add_users_to_worklist(k); + subsume_node(k, con); // Everybody using k now uses con return con; } // Now check for Identities - i = k->Identity(this); // Look for a nearby replacement - if( i != k ) { // Found? Return replacement! - NOT_PRODUCT( set_progress(); ) - add_users_to_worklist( k ); - subsume_node( k, i ); // Everybody using k now uses i + i = k->Identity(this); // Look for a nearby replacement + if (i != k) { // Found? Return replacement! + NOT_PRODUCT(set_progress();) + add_users_to_worklist(k); + subsume_node(k, i); // Everybody using k now uses i return i; } // Global Value Numbering i = hash_find_insert(k); // Check for pre-existing node - if( i && (i != k) ) { + if (i && (i != k)) { // Return the pre-existing node if it isn't dead - NOT_PRODUCT( set_progress(); ) - add_users_to_worklist( k ); - subsume_node( k, i ); // Everybody using k now uses i + NOT_PRODUCT(set_progress();) + add_users_to_worklist(k); + subsume_node(k, i); // Everybody using k now uses i return i; } @@ -1514,6 +1529,21 @@ C->set_root( transform(C->root())->as_Root() ); assert( C->top(), "missing TOP node" ); assert( C->root(), "missing root" ); + + // Eagerly remove castPP nodes here. CastPP nodes might not be + // removed in the subsequent IGVN phase if a node that changes + // in(1) of a castPP is processed prior to the castPP node. + for (uint i = 0; i < _worklist.size(); i++) { + Node* n = _worklist.at(i); + + if (n->is_ConstraintCast()) { + Node* nn = n->Identity(this); + if (nn != n) { + replace_node(n, nn); + --i; + } + } + } } //------------------------------transform-------------------------------------- diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/opto/phaseX.hpp --- a/hotspot/src/share/vm/opto/phaseX.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -440,6 +440,17 @@ // and dominator info to a fixed point. void optimize(); +#ifndef PRODUCT + void trace_PhaseIterGVN(Node* n, Node* nn, const Type* old_type); + void init_verifyPhaseIterGVN(); + void verify_PhaseIterGVN(); +#endif + +#ifdef ASSERT + void dump_infinite_loop_info(Node* n); + void trace_PhaseIterGVN_verbose(Node* n, int num_processed); +#endif + // Register a new node with the iter GVN pass without transforming it. // Used when we need to restructure a Region/Phi area and all the Regions // and Phis need to complete this one big transform before any other diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2420,7 +2420,7 @@ DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z , HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value), - HOTSPOT_JNI_SETBOOLEANFIELD_RETURN()) + HOTSPOT_JNI_SETSTATICBOOLEANFIELD_RETURN()) DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b , HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN()) diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1215,7 +1215,8 @@ // get run() method Method* m_oop = object->klass()->uncached_lookup_method( vmSymbols::run_method_name(), - vmSymbols::void_object_signature()); + vmSymbols::void_object_signature(), + Klass::normal); methodHandle m (THREAD, m_oop); if (m.is_null() || !m->is_method() || !m()->is_public() || m()->is_static()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method"); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/prims/nativeLookup.cpp --- a/hotspot/src/share/vm/prims/nativeLookup.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -408,7 +408,7 @@ // Find method and invoke standard lookup methodHandle method (THREAD, - klass->uncached_lookup_method(m_name, s_name)); + klass->uncached_lookup_method(m_name, s_name, Klass::normal)); address result = lookup(method, in_base_library, CATCH); assert(in_base_library, "must be in basic library"); guarantee(result != NULL, "must be non NULL"); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -53,7 +53,8 @@ } set_c1_count(MAX2(count / 3, 1)); - set_c2_count(MAX2(count - count / 3, 1)); + set_c2_count(MAX2(count - c1_count(), 1)); + FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count()); // Some inlining tuning #ifdef X86 diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -2402,6 +2402,10 @@ const int num_min_compiler_threads = (TieredCompilation && (TieredStopAtLevel >= CompLevel_full_optimization)) ? 2 : 1; status &=verify_min_value(CICompilerCount, num_min_compiler_threads, "CICompilerCount"); + if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) { + warning("The VM option CICompilerCountPerCPU overrides CICompilerCount."); + } + return status; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/compilationPolicy.cpp --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -182,6 +182,7 @@ // max(log2(8)-1,1) = 2 compiler threads on an 8-way machine. // May help big-app startup time. _compiler_count = MAX2(log2_intptr(os::active_processor_count())-1,1); + FLAG_SET_ERGO(intx, CICompilerCount, _compiler_count); } else { _compiler_count = CICompilerCount; } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -420,15 +420,9 @@ // frame[number_of_frames - 1 ] = on_stack_size(youngest) // frame[number_of_frames - 2 ] = on_stack_size(sender(youngest)) // frame[number_of_frames - 3 ] = on_stack_size(sender(sender(youngest))) - int caller_parms = callee_parameters; - if ((index == array->frames() - 1) && caller_was_method_handle) { - caller_parms = 0; - } - frame_sizes[number_of_frames - 1 - index] = BytesPerWord * array->element(index)->on_stack_size(caller_parms, - callee_parameters, + frame_sizes[number_of_frames - 1 - index] = BytesPerWord * array->element(index)->on_stack_size(callee_parameters, callee_locals, index == 0, - index == array->frames() - 1, popframe_extra_args); // This pc doesn't have to be perfect just good enough to identify the frame // as interpreted so the skeleton frame will be walkable diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -775,10 +775,13 @@ // going to be unwound. Dispatch to a shared runtime stub // which will cause the StackOverflowError to be fabricated // and processed. - // For stack overflow in deoptimization blob, cleanup thread. - if (thread->deopt_mark() != NULL) { - Deoptimization::cleanup_deopt_info(thread, NULL); - } + // Stack overflow should never occur during deoptimization: + // the compiled method bangs the stack by as much as the + // interpreter would need in case of a deoptimization. The + // deoptimization blob and uncommon trap blob bang the stack + // in a debug VM to verify the correctness of the compiled + // method stack banging. + assert(thread->deopt_mark() == NULL, "no stack overflow from deopt blob/uncommon trap"); Events::log_exception(thread, "StackOverflowError at " INTPTR_FORMAT, pc); return StubRoutines::throw_StackOverflowError_entry(); } @@ -946,14 +949,13 @@ * it gets turned into a tail-call on sparc, which runs into dtrace bug * 6254741. Once that is fixed we can remove the dummy return value. */ -int SharedRuntime::dtrace_object_alloc(oopDesc* o) { - return dtrace_object_alloc_base(Thread::current(), o); +int SharedRuntime::dtrace_object_alloc(oopDesc* o, int size) { + return dtrace_object_alloc_base(Thread::current(), o, size); } -int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o) { +int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o, int size) { assert(DTraceAllocProbes, "wrong call"); Klass* klass = o->klass(); - int size = o->size(); Symbol* name = klass->name(); HOTSPOT_OBJECT_ALLOC( get_java_tid(thread), diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -258,8 +258,8 @@ static void register_finalizer(JavaThread* thread, oopDesc* obj); // dtrace notifications - static int dtrace_object_alloc(oopDesc* o); - static int dtrace_object_alloc_base(Thread* thread, oopDesc* o); + static int dtrace_object_alloc(oopDesc* o, int size); + static int dtrace_object_alloc_base(Thread* thread, oopDesc* o, int size); static int dtrace_method_entry(JavaThread* thread, Method* m); static int dtrace_method_exit(JavaThread* thread, Method* m); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -142,7 +142,8 @@ count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2; } set_c1_count(MAX2(count / 3, 1)); - set_c2_count(MAX2(count - count / 3, 1)); + set_c2_count(MAX2(count - c1_count(), 1)); + FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count()); } void SimpleThresholdPolicy::set_carry_if_necessary(InvocationCounter *counter) { diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/vframeArray.cpp --- a/hotspot/src/share/vm/runtime/vframeArray.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -418,24 +418,20 @@ } -int vframeArrayElement::on_stack_size(int caller_actual_parameters, - int callee_parameters, +int vframeArrayElement::on_stack_size(int callee_parameters, int callee_locals, bool is_top_frame, - bool is_bottom_frame, int popframe_extra_stack_expression_els) const { assert(method()->max_locals() == locals()->size(), "just checking"); int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors(); int temps = expressions()->size(); - return Interpreter::size_activation(method(), + return Interpreter::size_activation(method()->max_stack(), temps + callee_parameters, popframe_extra_stack_expression_els, locks, - caller_actual_parameters, callee_parameters, callee_locals, - is_top_frame, - is_bottom_frame); + is_top_frame); } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/runtime/vframeArray.hpp --- a/hotspot/src/share/vm/runtime/vframeArray.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/runtime/vframeArray.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -85,10 +85,8 @@ // Returns the on stack word size for this frame // callee_parameters is the number of callee locals residing inside this frame - int on_stack_size(int caller_actual_parameters, - int callee_parameters, + int on_stack_size(int callee_parameters, int callee_locals, - bool is_bottom_frame, bool is_top_frame, int popframe_extra_stack_expression_els) const; diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/utilities/growableArray.hpp --- a/hotspot/src/share/vm/utilities/growableArray.hpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/utilities/growableArray.hpp Wed Apr 23 10:12:34 2014 +0200 @@ -147,6 +147,9 @@ } }; +template class GrowableArrayIterator; +template class GrowableArrayFilterIterator; + template class GrowableArray : public GenericGrowableArray { friend class VMStructs; @@ -243,6 +246,14 @@ return _data[_len-1]; } + GrowableArrayIterator begin() const { + return GrowableArrayIterator(this, 0); + } + + GrowableArrayIterator end() const { + return GrowableArrayIterator(this, length()); + } + void push(const E& elem) { append(elem); } E pop() { @@ -412,4 +423,83 @@ tty->print("}\n"); } +// Custom STL-style iterator to iterate over GrowableArrays +// It is constructed by invoking GrowableArray::begin() and GrowableArray::end() +template class GrowableArrayIterator : public StackObj { + friend class GrowableArray; + template friend class GrowableArrayFilterIterator; + + private: + const GrowableArray* _array; // GrowableArray we iterate over + int _position; // The current position in the GrowableArray + + // Private constructor used in GrowableArray::begin() and GrowableArray::end() + GrowableArrayIterator(const GrowableArray* array, int position) : _array(array), _position(position) { + assert(0 <= position && position <= _array->length(), "illegal position"); + } + + public: + GrowableArrayIterator& operator++() { ++_position; return *this; } + E operator*() { return _array->at(_position); } + + bool operator==(const GrowableArrayIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position == rhs._position; + } + + bool operator!=(const GrowableArrayIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position != rhs._position; + } +}; + +// Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate +template class GrowableArrayFilterIterator : public StackObj { + friend class GrowableArray; + + private: + const GrowableArray* _array; // GrowableArray we iterate over + int _position; // Current position in the GrowableArray + UnaryPredicate _predicate; // Unary predicate the elements of the GrowableArray should satisfy + + public: + GrowableArrayFilterIterator(const GrowableArrayIterator& begin, UnaryPredicate filter_predicate) + : _array(begin._array), _position(begin._position), _predicate(filter_predicate) { + // Advance to first element satisfying the predicate + while(_position != _array->length() && !_predicate(_array->at(_position))) { + ++_position; + } + } + + GrowableArrayFilterIterator& operator++() { + do { + // Advance to next element satisfying the predicate + ++_position; + } while(_position != _array->length() && !_predicate(_array->at(_position))); + return *this; + } + + E operator*() { return _array->at(_position); } + + bool operator==(const GrowableArrayIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position == rhs._position; + } + + bool operator!=(const GrowableArrayIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position != rhs._position; + } + + bool operator==(const GrowableArrayFilterIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position == rhs._position; + } + + bool operator!=(const GrowableArrayFilterIterator& rhs) { + assert(_array == rhs._array, "iterator belongs to different array"); + return _position != rhs._position; + } +}; + #endif // SHARE_VM_UTILITIES_GROWABLEARRAY_HPP diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/src/share/vm/utilities/xmlstream.cpp --- a/hotspot/src/share/vm/utilities/xmlstream.cpp Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/src/share/vm/utilities/xmlstream.cpp Wed Apr 23 10:12:34 2014 +0200 @@ -396,10 +396,10 @@ } void xmlStream::method_text(methodHandle method) { + ResourceMark rm; assert_if_no_error(inside_attrs(), "printing attributes"); if (method.is_null()) return; - //method->print_short_name(text()); - method->method_holder()->name()->print_symbol_on(text()); + text()->print(method->method_holder()->external_name()); print_raw(" "); // " " is easier for tools to parse than "::" method->name()->print_symbol_on(text()); print_raw(" "); // separator diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/TEST.groups Wed Apr 23 10:12:34 2014 +0200 @@ -136,7 +136,8 @@ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/tiered/NonTieredLevelsTest.java \ - compiler/tiered/TieredLevelsTest.java + compiler/tiered/TieredLevelsTest.java \ + compiler/intrinsics/bmi/verifycode # Compact 2 adds full VM tests compact2 = \ diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/EscapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/EscapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright 2014 SAP AG. 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 8038048 + * @summary assert(null_obj->escape_state() == PointsToNode::NoEscape,etc) + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DoEscapeAnalysis -XX:-TieredCompilation -Xbatch TestUnsafePutAddressNullObjMustNotEscape + * @author Richard Reingruber richard DOT reingruber AT sap DOT com + */ + +import java.lang.reflect.Field; +import sun.misc.Unsafe; + +public class TestUnsafePutAddressNullObjMustNotEscape { + + public static Unsafe usafe; + public static long mem; + public static long checksum; + + public static void main(String[] args) throws Exception { + System.out.println("EXECUTING test."); + + { + System.out.println("Acquiring sun.misc.Unsafe.theUnsafe using reflection."); + getUnsafe(); + System.out.println("Allocating raw memory."); + mem = (usafe.allocateMemory(1024) + 8L) & ~7L; + System.out.println("Triggering JIT compilation of the test method"); + triggerJitCompilationOfTestMethod(); + } + + System.out.println("SUCCESSFULLY passed test."); + } + + public static void triggerJitCompilationOfTestMethod() { + long sum = 0; + for (int ii = 50000; ii >= 0; ii--) { + sum = testMethod(); + } + checksum = sum; + } + + public static class IDGen { + private static long id; + public long nextId() { + return id++; + } + } + + public static long testMethod() { + // dummy alloc to trigger escape analysis + IDGen gen = new IDGen(); + // StoreP of null_obj to raw mem triggers assertion in escape analysis + usafe.putAddress(mem, 0L); + return gen.nextId(); + } + + private static void getUnsafe() throws Exception { + Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + usafe = (sun.misc.Unsafe) field.get(null); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build AddnTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestI + */ + +import java.lang.reflect.Method; + +public class AddnTestI extends BmiIntrinsicBase.BmiTestCase { + + protected AddnTestI(Method method) { + super(method); + // from intel manual VEX.NDS.LZ.0F38.W0 F2 /r, example c4e260f2c2 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF2}; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(AddnTestI::new, TestAndnI.AndnIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(AddnTestI::new, TestAndnI.AndnICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build AddnTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestL + */ + +import java.lang.reflect.Method; + +public class AddnTestL extends AddnTestI { + + protected AddnTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(AddnTestL::new, TestAndnL.AndnLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(AddnTestL::new, TestAndnL.AndnLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsiTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestI + */ + +import java.lang.reflect.Method; + +public class BlsiTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsiTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /3 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_1000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsiTestI::new, TestBlsiI.BlsiIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsiTestI::new, TestBlsiI.BlsiICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsiTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestL + */ + +import java.lang.reflect.Method; + +public class BlsiTestL extends BlsiTestI { + + protected BlsiTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsiTestL::new, TestBlsiL.BlsiLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsiTestL::new, TestBlsiL.BlsiLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsmskTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestI + */ + +import java.lang.reflect.Method; + +public class BlsmskTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsmskTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /2 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_0000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsmskTestI::new, TestBlsmskI.BlsmskIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsmskTestI::new, TestBlsmskI.BlsmskICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsmskTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestL + */ + +import java.lang.reflect.Method; + +public class BlsmskTestL extends BlsmskTestI { + + protected BlsmskTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsmskTestL::new, TestBlsmskL.BlsmskLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsmskTestL::new, TestBlsmskL.BlsmskLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsrTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestI + */ + +import java.lang.reflect.Method; + +public class BlsrTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsrTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /1 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0000_1000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsrTestI::new, TestBlsrI.BlsrIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsrTestI::new, TestBlsrI.BlsrICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsrTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestL + */ + +import java.lang.reflect.Method; + +public class BlsrTestL extends BlsrTestI { + + protected BlsrTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsrTestL::new, TestBlsrL.BlsrLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsrTestL::new, TestBlsrL.BlsrLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.Utils; +import sun.hotspot.code.NMethod; +import sun.hotspot.cpuinfo.CPUInfo; + +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.function.Function; + +public class BmiIntrinsicBase extends CompilerWhiteBoxTest { + + protected BmiIntrinsicBase(BmiTestCase testCase) { + super(testCase); + } + + public static void verifyTestCase(Function constructor, Method... methods) throws Exception { + for (Method method : methods) { + new BmiIntrinsicBase(constructor.apply(method)).test(); + } + } + + @Override + protected void test() throws Exception { + BmiTestCase bmiTestCase = (BmiTestCase) testCase; + + if (!(Platform.isX86() || Platform.isX64())) { + System.out.println("Unsupported platform, test SKIPPED"); + return; + } + + if (!Platform.isServer()) { + System.out.println("Not server VM, test SKIPPED"); + return; + } + + if (!CPUInfo.hasFeature(bmiTestCase.getCpuFlag())) { + System.out.println("Unsupported hardware, no required CPU flag " + bmiTestCase.getCpuFlag() + " , test SKIPPED"); + return; + } + + if (!Boolean.valueOf(getVMOption(bmiTestCase.getVMFlag()))) { + System.out.println("VM flag " + bmiTestCase.getVMFlag() + " disabled, test SKIPPED"); + return; + } + + System.out.println(testCase.name()); + + switch (MODE) { + case "compiled mode": + case "mixed mode": + if (TIERED_COMPILATION && TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_MAX) { + System.out.println("TieredStopAtLevel value (" + TIERED_STOP_AT_LEVEL + ") is too low, test SKIPPED"); + return; + } + deoptimize(); + compileAtLevelAndCheck(CompilerWhiteBoxTest.COMP_LEVEL_MAX); + break; + case "interpreted mode": // test is not applicable in this mode; + System.err.println("Warning: This test is not applicable in mode: " + MODE); + break; + default: + throw new AssertionError("Test bug, unknown VM mode: " + MODE); + } + } + + protected void compileAtLevelAndCheck(int level) { + WHITE_BOX.enqueueMethodForCompilation(method, level); + waitBackgroundCompilation(); + checkCompilation(method, level); + checkEmittedCode(method); + } + + protected void checkCompilation(Executable executable, int level) { + if (!WHITE_BOX.isMethodCompiled(executable)) { + throw new AssertionError("Test bug, expected compilation (level): " + level + ", but not compiled" + WHITE_BOX.isMethodCompilable(executable, level)); + } + final int compilationLevel = WHITE_BOX.getMethodCompilationLevel(executable); + if (compilationLevel != level) { + throw new AssertionError("Test bug, expected compilation (level): " + level + ", but level: " + compilationLevel); + } + } + + protected void checkEmittedCode(Executable executable) { + final byte[] nativeCode = NMethod.get(executable, false).insts; + if (!((BmiTestCase) testCase).verifyPositive(nativeCode)) { + throw new AssertionError(testCase.name() + "CPU instructions expected not found: " + Utils.toHexString(nativeCode)); + } else { + System.out.println("CPU instructions found, PASSED"); + } + } + + abstract static class BmiTestCase implements CompilerWhiteBoxTest.TestCase { + private final Method method; + protected byte[] instrMask; + protected byte[] instrPattern; + protected boolean isLongOperation; + + public BmiTestCase(Method method) { + this.method = method; + } + + @Override + public String name() { + return method.toGenericString(); + } + + @Override + public Executable getExecutable() { + return method; + } + + @Override + public Callable getCallable() { + return null; + } + + @Override + public boolean isOsr() { + return false; + } + + protected int countCpuInstructions(byte[] nativeCode) { + int count = 0; + int patternSize = Math.min(instrMask.length, instrPattern.length); + boolean found; + Asserts.assertGreaterThan(patternSize, 0); + for (int i = 0, n = nativeCode.length - patternSize; i < n; i++) { + found = true; + for (int j = 0; j < patternSize; j++) { + if ((nativeCode[i + j] & instrMask[j]) != instrPattern[j]) { + found = false; + break; + } + } + if (found) { + ++count; + i += patternSize - 1; + } + } + return count; + } + + public boolean verifyPositive(byte[] nativeCode) { + final int cnt = countCpuInstructions(nativeCode); + if (Platform.isX86()) { + return cnt >= (isLongOperation ? 2 : 1); + } else { + return Platform.isX64() && cnt >= 1; + } + } + + protected String getCpuFlag() { + return "bmi1"; + } + + protected String getVMFlag() { + return "UseBMI1Instructions"; + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build LZcntTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestI + */ + +import java.lang.reflect.Method; + +public class LZcntTestI extends BmiIntrinsicBase.BmiTestCase { + + protected LZcntTestI(Method method) { + super(method); + instrMask = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x0F, (byte) 0xBD}; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("class java.lang.Integer should be loaded. Proof: " + Integer.class); + BmiIntrinsicBase.verifyTestCase(LZcntTestI::new, TestLzcntI.LzcntIExpr.class.getDeclaredMethods()); + } + + @Override + protected String getVMFlag() { + return "UseCountLeadingZerosInstruction"; + } + + @Override + protected String getCpuFlag() { + return "lzcnt"; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build LZcntTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestL + */ + +import com.oracle.java.testlibrary.Platform; + +import java.lang.reflect.Method; + +public class LZcntTestL extends LZcntTestI { + + protected LZcntTestL(Method method) { + super(method); + isLongOperation = true; + if (Platform.isX64()) { + instrMask = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBD}; + } + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("classes java.lang.Long should be loaded. Proof: " + Long.class); + BmiIntrinsicBase.verifyTestCase(LZcntTestL::new, TestLzcntL.LzcntLExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build TZcntTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestI + */ + +import java.lang.reflect.Method; + +public class TZcntTestI extends BmiIntrinsicBase.BmiTestCase { + + protected TZcntTestI(Method method) { + super(method); + instrMask = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x0F, (byte) 0xBC}; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("class java.lang.Integer should be loaded. Proof: " + Integer.class); + BmiIntrinsicBase.verifyTestCase(TZcntTestI::new, TestTzcntI.TzcntIExpr.class.getDeclaredMethods()); + } + + @Override + protected String getVMFlag() { + return "UseCountTrailingZerosInstruction"; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build TZcntTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestL + */ + +import com.oracle.java.testlibrary.Platform; + +import java.lang.reflect.Method; + +public class TZcntTestL extends TZcntTestI { + + protected TZcntTestL(Method method) { + super(method); + isLongOperation = true; + if (Platform.isX64()) { + instrMask = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBC}; + } + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("classes java.lang.Long should be loaded. Proof: " + Long.class); + BmiIntrinsicBase.verifyTestCase(TZcntTestL::new, TestTzcntL.TzcntLExpr.class.getDeclaredMethods()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +import java.util.function.BooleanSupplier; + +/** + * Base for all RTM-related CLI tests. + */ +public abstract class RTMGenericCommandLineOptionTest + extends CommandLineOptionTest { + protected static final String RTM_INSTR_ERROR + = "RTM instructions are not available on this CPU"; + protected static final String RTM_UNSUPPORTED_VM_ERROR + = "RTM locking optimization is not supported in this VM"; + protected static final String RTM_ABORT_RATIO_WARNING + = "RTMAbortRatio must be in the range 0 to 100, resetting it to 50"; + protected static final String RTM_FOR_STACK_LOCKS_WARNING + = "UseRTMForStackLocks flag should be off when UseRTMLocking " + + "flag is off"; + protected static final String RTM_COUNT_INCR_WARNING + = "RTMTotalCountIncrRate must be a power of 2, resetting it to 64"; + protected static final String RTM_BIASED_LOCKING_WARNING + = "Biased locking is not supported with RTM locking; " + + "ignoring UseBiasedLocking flag"; + + protected final String optionName; + protected final String errorMessage; + protected final String experimentalOptionError; + protected final boolean isExperimental; + protected final boolean isBoolean; + protected final String defaultValue; + protected final String[] optionValues; + + /** + * Constructs new genetic RTM CLI test, for option {@code optionName} which + * has default value {@code defaultValue}. Test cases will use option's + * values passed via {@code optionValues} for verification of correct + * option processing. + * + * Test constructed using this ctor will be started on any cpu regardless + * it's architecture and supported/unsupported features. + * + * @param predicate predicate responsible for test's preconditions check + * @param optionName name of option to be tested + * @param isBoolean {@code true} if option is binary + * @param isExperimental {@code true} if option is experimental + * @param defaultValue default value of tested option + * @param optionValues different option values + */ + public RTMGenericCommandLineOptionTest(BooleanSupplier predicate, + String optionName, boolean isBoolean, boolean isExperimental, + String defaultValue, String... optionValues) { + super(predicate); + this.optionName = optionName; + this.isExperimental = isExperimental; + this.isBoolean = isBoolean; + this.defaultValue = defaultValue; + this.optionValues = optionValues; + this.errorMessage = CommandLineOptionTest. + getUnrecognizedOptionErrorMessage(optionName); + this.experimentalOptionError = CommandLineOptionTest. + getExperimentalOptionErrorMessage(optionName); + } + + @Override + public void runTestCases() throws Throwable { + if (Platform.isX86() || Platform.isX64()) { + if (Platform.isServer() && !Platform.isEmbedded()) { + runX86SupportedVMTestCases(); + } else { + runX86UnsupportedVMTestCases(); + } + } else { + runNonX86TestCases(); + } + } + + /** + * Runs test cases on X86 CPU if VM supports RTM locking. + * @throws Throwable + */ + protected void runX86SupportedVMTestCases() throws Throwable { + runGenericX86TestCases(); + } + + /** + * Runs test cases on non-X86 CPU if VM does not support RTM locking. + * @throws Throwable + */ + protected void runX86UnsupportedVMTestCases() throws Throwable { + runGenericX86TestCases(); + } + + /** + * Runs test cases on non-X86 CPU. + * @throws Throwable + */ + protected void runNonX86TestCases() throws Throwable { + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + prepareOptionValue(defaultValue)); + } + + /** + * Runs generic X86 test cases. + * @throws Throwable + */ + protected void runGenericX86TestCases() throws Throwable { + verifyJVMStartup(); + verifyOptionValues(); + } + + protected void verifyJVMStartup() throws Throwable { + String optionValue = prepareOptionValue(defaultValue); + if (isExperimental) { + // verify that option is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[] { experimentalOptionError }, + new String[] { errorMessage }, ExitCode.FAIL, + optionValue); + // verify that it could be passed if experimental options + // are unlocked + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { + experimentalOptionError, + errorMessage + }, + ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + optionValue); + } else { + // verify that option could be passed + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{errorMessage}, ExitCode.OK, optionValue); + } + } + + protected void verifyOptionValues() throws Throwable { + // verify default value + if (isExperimental) { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + } else { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue); + } + // verify other specified option values + if (optionValues == null) { + return; + } + + for (String value : optionValues) { + if (isExperimental) { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + value, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue(value)); + } else { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + value, prepareOptionValue(value)); + } + } + } + + protected String prepareOptionValue(String value) { + if (isBoolean) { + return CommandLineOptionTest.prepareBooleanFlag(optionName, + Boolean.valueOf(value)); + } else { + return String.format("-XX:%s=%s", optionName, value); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +import java.util.List; +import java.util.LinkedList; + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Base for all RTM-related CLI tests on options whose processing depends + * on UseRTMLocking value. + * + * Since UseRTMLocking option could be used when both CPU and VM supports RTM + * locking, this test will be skipped on all unsupported configurations. + */ +public abstract class RTMLockingAwareTest + extends RTMGenericCommandLineOptionTest { + protected final String warningMessage; + protected final String[] correctValues; + protected final String[] incorrectValues; + /** + * Constructs new test for option {@code optionName} that should be executed + * only on CPU with RTM support. + * Test will be executed using set of correct values from + * {@code correctValues} and set of incorrect values from + * {@code incorrectValues}. + * + * @param optionName name of option to be tested + * @param isBoolean {@code true} if tested option is binary + * @param isExperimental {@code true} if tested option is experimental + * @param defaultValue default value of tested option + * @param correctValues array with correct values, that should not emit + * {@code warningMessage} to VM output + * @param incorrectValues array with incorrect values, that should emit + * {@code waningMessage} to VM output + * @param warningMessage warning message associated with tested option + */ + protected RTMLockingAwareTest(String optionName, boolean isBoolean, + boolean isExperimental, String defaultValue, + String[] correctValues, String[] incorrectValues, + String warningMessage) { + super(new AndPredicate(new SupportedCPU(), new SupportedVM()), + optionName, isBoolean, isExperimental, defaultValue); + this.correctValues = correctValues; + this.incorrectValues = incorrectValues; + this.warningMessage = warningMessage; + } + + @Override + protected void verifyJVMStartup() throws Throwable { + // Run generic sanity checks + super.verifyJVMStartup(); + // Verify how option values will be processed depending on + // UseRTMLocking value. + if (correctValues != null) { + for (String correctValue : correctValues) { + // For correct values it is expected to see no warnings + // regardless to UseRTMLocking + verifyStartupWarning(correctValue, true, false); + verifyStartupWarning(correctValue, false, false); + } + } + + if (incorrectValues != null) { + for (String incorrectValue : incorrectValues) { + // For incorrect values it is expected to see warning + // only with -XX:+UseRTMLocking + verifyStartupWarning(incorrectValue, true, true); + verifyStartupWarning(incorrectValue, false, false); + } + } + } + + @Override + protected void verifyOptionValues() throws Throwable { + super.verifyOptionValues(); + // Verify how option values will be setup after processing + // depending on UseRTMLocking value + if (correctValues != null) { + for (String correctValue : correctValues) { + // Correct value could be set up regardless to UseRTMLocking + verifyOptionValues(correctValue, false, correctValue); + verifyOptionValues(correctValue, true, correctValue); + } + } + + if (incorrectValues != null) { + for (String incorrectValue : incorrectValues) { + // With -XX:+UseRTMLocking, incorrect value will be changed to + // default value. + verifyOptionValues(incorrectValue, false, incorrectValue); + verifyOptionValues(incorrectValue, true, defaultValue); + } + } + } + + private void verifyStartupWarning(String value, boolean useRTMLocking, + boolean isWarningExpected) throws Throwable { + String warnings[] = new String[] { warningMessage }; + List options = new LinkedList<>(); + options.add(CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", + useRTMLocking)); + + if (isExperimental) { + options.add(CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + } + options.add(prepareOptionValue(value)); + + CommandLineOptionTest.verifySameJVMStartup( + (isWarningExpected ? warnings : null), + (isWarningExpected ? null : warnings), + ExitCode.OK, options.toArray(new String[options.size()])); + } + + private void verifyOptionValues(String value, boolean useRTMLocking, + String expectedValue) throws Throwable { + List options = new LinkedList<>(); + options.add(CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", + useRTMLocking)); + + if (isExperimental) { + options.add(CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + } + options.add(prepareOptionValue(value)); + + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + expectedValue, options.toArray(new String[options.size()])); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +import java.util.function.BooleanSupplier; + +public abstract class TestPrintPreciseRTMLockingStatisticsBase + extends RTMGenericCommandLineOptionTest { + protected static final String DEFAULT_VALUE = "false"; + + protected TestPrintPreciseRTMLockingStatisticsBase( + BooleanSupplier predicate) { + super(predicate, "PrintPreciseRTMLockingStatistics", true, false, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE); + } + + @Override + protected void runNonX86TestCases() throws Throwable { + verifyJVMStartup(); + verifyOptionValues(); + } + + @Override + protected void verifyJVMStartup() throws Throwable { + if (Platform.isServer()) { + if (!Platform.isDebugBuild()) { + String errorMessage = CommandLineOptionTest. + getDiagnosticOptionErrorMessage(optionName); + // verify that option is actually diagnostic + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + prepareOptionValue("true")); + + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { errorMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + prepareOptionValue("true")); + } else { + CommandLineOptionTest.verifySameJVMStartup( + null, null, ExitCode.OK, prepareOptionValue("true")); + } + } else { + String errorMessage = CommandLineOptionTest. + getUnrecognizedOptionErrorMessage(optionName); + + CommandLineOptionTest.verifySameJVMStartup( + new String[]{errorMessage}, null, ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + prepareOptionValue("true")); + } + } + + @Override + protected void verifyOptionValues() throws Throwable { + if (Platform.isServer()) { + // Verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs with + * rtm support and on VM with rtm locking support, + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + extends TestPrintPreciseRTMLockingStatisticsBase { + private TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void verifyOptionValues() throws Throwable { + super.verifyOptionValues(); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + "-XX:+UseRTMLocking"); + + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + "-XX:-UseRTMLocking", prepareOptionValue("true")); + + // verify that option could be turned on + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + "-XX:+UseRTMLocking", prepareOptionValue("true")); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() + .test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs without + * rtm support and/or unsupported VM. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + extends TestPrintPreciseRTMLockingStatisticsBase { + private TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM()))); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() + .test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify RTMAbortRatio option processing on CPU with rtm + * support and on VM with rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatioOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnSupportedConfig + */ + +public class TestRTMAbortRatioOptionOnSupportedConfig + extends RTMLockingAwareTest { + private static final String DEFAULT_VALUE = "50"; + + private TestRTMAbortRatioOptionOnSupportedConfig() { + super("RTMAbortRatio", false, true, + TestRTMAbortRatioOptionOnSupportedConfig.DEFAULT_VALUE, + /* correct values */ + new String[] { "0", "20", "100" }, + /* incorrect values */ + new String[] { "-1", "101" }, + RTMGenericCommandLineOptionTest.RTM_ABORT_RATIO_WARNING); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatioOptionOnSupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify RTMAbortRatio option processing on CPU without rtm + * support or on VM that does not support rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatioOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestRTMAbortRatioOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "50"; + + private TestRTMAbortRatioOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedVM(), + new SupportedCPU())), + "RTMAbortRatio", false, true, + TestRTMAbortRatioOptionOnUnsupportedConfig.DEFAULT_VALUE, + "0", "10", "100", "200"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatioOptionOnUnsupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMAbortThresholdOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortThresholdOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of RTMAbortThreshold option. + * @library /testlibrary + * @build TestRTMAbortThresholdOption + * @run main/othervm TestRTMAbortThresholdOption + */ + +public class TestRTMAbortThresholdOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "1000"; + + private TestRTMAbortThresholdOption() { + super(Boolean.TRUE::booleanValue, "RTMAbortThreshold", false, true, + TestRTMAbortThresholdOption.DEFAULT_VALUE, + "0", "42", "100", "10000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortThresholdOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of RTMLockingCalculationDelay option. + * @library /testlibrary + * @build TestRTMLockingCalculationDelayOption + * @run main/othervm TestRTMLockingCalculationDelayOption + */ + +public class TestRTMLockingCalculationDelayOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "0"; + + private TestRTMLockingCalculationDelayOption() { + super(Boolean.TRUE::booleanValue, "RTMLockingCalculationDelay", false, + true, TestRTMLockingCalculationDelayOption.DEFAULT_VALUE); + } + + public static void main(String agrs[]) throws Throwable { + new TestRTMLockingCalculationDelayOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMLockingThresholdOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMLockingThresholdOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of RTMLockingThreshold option. + * @library /testlibrary + * @build TestRTMLockingThresholdOption + * @run main/othervm TestRTMLockingThresholdOption + */ + +public class TestRTMLockingThresholdOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "10000"; + + private TestRTMLockingThresholdOption() { + super(Boolean.TRUE::booleanValue, "RTMLockingThreshold", false, true, + TestRTMLockingThresholdOption.DEFAULT_VALUE); + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingThresholdOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of RTMRetryCount option. + * @library /testlibrary + * @build TestRTMRetryCountOption + * @run main/othervm TestRTMRetryCountOption + */ + +public class TestRTMRetryCountOption extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "5"; + + private TestRTMRetryCountOption() { + super(Boolean.TRUE::booleanValue, "RTMRetryCount", false, false, + TestRTMRetryCountOption.DEFAULT_VALUE, + "0", "10", "100", "1000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMRetryCountOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMSpinLoopCountOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMSpinLoopCountOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of RTMSpinLoopCount option. + * @library /testlibrary + * @build TestRTMSpinLoopCountOption + * @run main/othervm TestRTMSpinLoopCountOption + */ + +public class TestRTMSpinLoopCountOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "100"; + + private TestRTMSpinLoopCountOption() { + super(Boolean.TRUE::booleanValue, "RTMSpinLoopCount", false, true, + TestRTMSpinLoopCountOption.DEFAULT_VALUE, + "0", "10", "42", "1000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMSpinLoopCountOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify RTMTotalCountIncrRate option processing on CPU with + * rtm support and on VM with rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRateOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestRTMTotalCountIncrRateOptionOnSupportedConfig + */ + +public class TestRTMTotalCountIncrRateOptionOnSupportedConfig + extends RTMLockingAwareTest { + private static final String DEFAULT_VALUE = "64"; + + private TestRTMTotalCountIncrRateOptionOnSupportedConfig() { + super("RTMTotalCountIncrRate", false, true, + TestRTMTotalCountIncrRateOptionOnSupportedConfig.DEFAULT_VALUE, + /* correct values */ + new String[] { "1", "2", "128", "1024" }, + /* incorrect values */ + new String[] { "-1", "0", "3", "42" }, + RTMGenericCommandLineOptionTest.RTM_COUNT_INCR_WARNING); + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRateOptionOnSupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * @test + * @bug 8031320 + * @summary Verify RTMTotalCountIncrRate option processing on CPU without + * rtm support and/or on VM without rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + */ + +public class TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "64"; + + private TestRTMTotalCountIncrRateOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "RTMTotalCountIncrRate", false, true, + TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + .DEFAULT_VALUE, + "-1", "0", "42", "128"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRateOptionOnUnsupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMDeopt option processing on CPUs with rtm support + * when rtm locking is supported by VM. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseRTMDeoptOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMDeoptOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMDeoptOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + // verify that option could be turned on + CommandLineOptionTest.verifySameJVMStartup( + null, null, ExitCode.OK, "-XX:+UseRTMDeopt"); + // verify that option could be turned off + CommandLineOptionTest.verifySameJVMStartup( + null, null, ExitCode.OK, "-XX:-UseRTMDeopt"); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, + "-XX:+UseRTMLocking"); + // verify that option is off when UseRTMLocking is off + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + "false", "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt"); + // verify that option could be turned on + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + "true", "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeoptOptionOnSupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMDeopt option processing on CPUs without rtm support + * or on VMs without rtm locking support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseRTMDeoptOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMDeoptOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMDeoptOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "UseRTMDeopt", true, false, + TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, "true"); + } + + @Override + protected void runX86SupportedVMTestCases() throws Throwable { + super.verifyJVMStartup(); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue); + // verify that until RTMLocking is not used, value + // will be set to default false. + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue, "-XX:+UseRTMDeopt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeoptOptionOnUnsupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMForStackLocks option processing on CPU with + * rtm support when VM supports rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocksOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseRTMForStackLocksOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMForStackLocksOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMForStackLocksOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + String errorMessage + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + "UseRTMForStackLocks"); + String warningMessage + = RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING; + + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + "-XX:+UseRTMForStackLocks"); + // verify that we get a warning when trying to use rtm for stack + // lock, but not using rtm locking. + CommandLineOptionTest.verifySameJVMStartup( + new String[] { warningMessage }, null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMForStackLocks", + "-XX:-UseRTMLocking"); + // verify that we don't get a warning when no using rtm for stack + // lock and not using rtm locking. + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMForStackLocks", + "-XX:-UseRTMLocking"); + // verify that we don't get a warning when using rtm for stack + // lock and using rtm locking. + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMForStackLocks", + "-XX:+UseRTMLocking"); + // verify that default value if false + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that default value is false even with +UseRTMLocking + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that we can turn the option on + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseRTMForStackLocks"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocksOptionOnSupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMForStackLocks option processing on CPUs without + * rtm support and/or on VMs without rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocksOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseRTMForStackLocksOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMForStackLocksOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMForStackLocksOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "UseRTMForStackLocks", true, true, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + "true"); + } + + @Override + protected void runX86SupportedVMTestCases() throws Throwable { + // verify that option is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ experimentalOptionError }, + null, ExitCode.FAIL, prepareOptionValue("true")); + + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ experimentalOptionError }, + null, ExitCode.FAIL, prepareOptionValue("false")); + + // verify that if we turn it on, then VM output will contain + // warning saying that this option could be turned on only + // when we use rtm locking + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ + RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING + }, + null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue("true") + ); + // verify that options is turned off by default + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that it could not be turned on without rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue("true")); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocksOptionOnUnsupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMLocking option processing on CPU with rtm support and + * on VM with rtm-locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + String unrecongnizedOption + = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( + "UseRTMLocking"); + // verify that there are no warning or error in VM output + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{ + RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, + unrecongnizedOption + }, ExitCode.OK, "-XX:+UseRTMLocking" + ); + + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{ + RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, + unrecongnizedOption + }, ExitCode.OK, "-XX:-UseRTMLocking" + ); + // verify that UseRTMLocking is of by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE); + // verify that we can change UseRTMLocking value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, + "-XX:-UseRTMLocking"); + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + "true", "-XX:+UseRTMLocking"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnSupportedConfig().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMLocking option processing on CPU without + * rtm support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnUnsupportedCPU + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedCPU + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnUnsupportedCPU + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnUnsupportedCPU() { + super(new AndPredicate(new NotPredicate(new SupportedCPU()), + new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + String unrecongnizedOption + = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( + "UseRTMLocking"); + String errorMessage = RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR; + + if (Platform.isX86() || Platform.isX64()) { + // verify that we get an error when use +UseRTMLocking + // on unsupported CPU + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, + new String[] { unrecongnizedOption }, + ExitCode.FAIL, "-XX:+UseRTMLocking"); + // verify that we can pass -UseRTMLocking without + // getting any error messages + CommandLineOptionTest.verifySameJVMStartup( + null, + new String[]{ + errorMessage, + unrecongnizedOption + }, ExitCode.OK, "-XX:-UseRTMLocking"); + + // verify that UseRTMLocking is false by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE); + } else { + // verify that on non-x86 CPUs RTMLocking could not be used + CommandLineOptionTest.verifySameJVMStartup( + new String[] { unrecongnizedOption }, + null, ExitCode.FAIL, "-XX:+UseRTMLocking"); + + CommandLineOptionTest.verifySameJVMStartup( + new String[] { unrecongnizedOption }, + null, ExitCode.FAIL, "-XX:-UseRTMLocking"); + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnUnsupportedCPU().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify UseRTMLocking option processing on CPU with rtm support + * in case when VM should not support this option. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnUnsupportedVM + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedVM + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnUnsupportedVM + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnUnsupportedVM() { + super(new AndPredicate(new SupportedCPU(), + new NotPredicate(new SupportedVM()))); + } + @Override + public void runTestCases() throws Throwable { + String errorMessage + = RTMGenericCommandLineOptionTest.RTM_UNSUPPORTED_VM_ERROR; + // verify that we can't use +UseRTMLocking + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + "-XX:+UseRTMLocking"); + // verify that we can turn it off + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { errorMessage }, ExitCode.OK, + "-XX:-UseRTMLocking"); + // verify that it is off by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnUnsupportedVM().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of UseRTMLocking and UseBiasedLocking + * options combination on CPU and VM with rtm support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionWithBiasedLocking + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionWithBiasedLocking + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionWithBiasedLocking + extends CommandLineOptionTest { + private TestUseRTMLockingOptionWithBiasedLocking() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + String warningMessage + = RTMGenericCommandLineOptionTest.RTM_BIASED_LOCKING_WARNING; + // verify that we will not get a warning + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + "-XX:+UseRTMLocking", "-XX:-UseBiasedLocking"); + // verify that we will get a warning + CommandLineOptionTest.verifySameJVMStartup( + new String[] { warningMessage }, null, ExitCode.OK, + "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); + // verify that UseBiasedLocking is false when we use rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", + "false", "-XX:+UseRTMLocking"); + // verify that we can't turn on biased locking when + // using rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", + "false", "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionWithBiasedLocking().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify processing of UseRTMXendForLockBusy option. + * @library /testlibrary + * @build TestUseRTMXendForLockBusyOption + * @run main/othervm TestUseRTMXendForLockBusyOption + */ + +public class TestUseRTMXendForLockBusyOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "true"; + + public TestUseRTMXendForLockBusyOption() { + super(Boolean.TRUE::booleanValue, "UseRTMXendForLockBusy", true, true, + TestUseRTMXendForLockBusyOption.DEFAULT_VALUE, "true"); + } + + public static void main(String agrs[]) throws Throwable { + new TestUseRTMXendForLockBusyOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMAbortRatio affects amount of aborts before + * deoptimization. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that method will be deoptimized on high abort ratio + * as soon as abort ratio reaches RTMAbortRatio's value. + */ +public class TestRTMAbortRatio extends CommandLineOptionTest { + private TestRTMAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyAbortRatio(0, false); + verifyAbortRatio(10, false); + verifyAbortRatio(50, false); + verifyAbortRatio(100, false); + + verifyAbortRatio(0, true); + verifyAbortRatio(10, true); + verifyAbortRatio(50, true); + verifyAbortRatio(100, true); + } + + private void verifyAbortRatio(int abortRatio, boolean useStackLock) + throws Throwable { + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:+UseRTMDeopt", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMAbortThreshold=0", + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + 10 * Test.TOTAL_ITERATIONS), + CommandLineOptionTest.prepareNumericFlag("RTMAbortRatio", + abortRatio), + "-XX:+PrintPreciseRTMLockingStatistics", + test.getClass().getName(), + Boolean.toString(!useStackLock)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry."); + + RTMLockingStatistics lock = statistics.get(0); + int actualRatio; + + if (lock.getTotalAborts() == 1L) { + actualRatio = 0; + } else { + actualRatio = (int) (lock.getTotalLocks() + / (lock.getTotalAborts() - 1L)); + } + + Asserts.assertLTE(actualRatio, abortRatio, String.format( + "Actual abort ratio (%d) should lower or equal to " + + "specified (%d).", actualRatio, abortRatio)); + } + + /** + * Force abort after {@code Test.WARMUP_ITERATIONS} is done. + */ + public static class Test implements CompilableTest { + private static final int TOTAL_ITERATIONS = 10000; + private static final int WARMUP_ITERATIONS = 1000; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + Unsafe.class.getName() + "::addressSize" + }; + } + + public void lock(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + t.lock(i >= Test.WARMUP_ITERATIONS); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatio().test(); + } +} + diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMAbortThreshold option affects + * amount of aborts after which abort ratio is calculated. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortThreshold + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortThreshold + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that on RTMAbortThreshold option actually affects how soon + * method will be deoptimized on high abort ratio. + */ +public class TestRTMAbortThreshold extends CommandLineOptionTest { + private TestRTMAbortThreshold() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyAbortThreshold(false, 1); + verifyAbortThreshold(false, 10); + verifyAbortThreshold(false, 1000); + + verifyAbortThreshold(true, 1); + verifyAbortThreshold(true, 10); + verifyAbortThreshold(true, 1000); + } + + private void verifyAbortThreshold(boolean useStackLock, + long abortThreshold) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMDeopt", + "-XX:RTMAbortRatio=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + abortThreshold), + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + provoker.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalLocks(), abortThreshold, + String.format("Expected that method with rtm lock elision was" + + " deoptimized after %d lock attempts", + abortThreshold)); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortThreshold().test(); + } +} + diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that if we use RTMDeopt, then deoptimization + * caused by reason other then rtm_state_change will reset + * method's RTM state. And if we don't use RTMDeopt, then + * RTM state remain the same after such deoptimization. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAfterNonRTMDeopt + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAfterNonRTMDeopt + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * To verify that with +UseRTMDeopt method's RTM state will be + * changed to ProfileRTM on deoptimization unrelated to + * rtm_state_change following sequence of events is used: + *
+ *
+ *     rtm state ^
+ *               |
+ *       UseRTM  |      ******|     ******
+ *               |            |
+ *   ProfileRTM  |******|     |*****|
+ *               |      |     |     |
+ *              0-------|-----|-----|---------------------> time
+ *                      |     |     \ force abort
+ *                      |     |
+ *                      |     \ force deoptimization
+ *                      |
+ *                      \ force xabort
+ * 
+ * When xabort is forced by native method call method should + * change it's state to UseRTM, because we use RTMAbortRatio=100 + * and low RTMLockingThreshold, so at this point actual abort + * ratio will be below 100% and there should be enough lock + * attempts to recompile method without RTM profiling. + */ +public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { + private static final int ABORT_THRESHOLD = 1000; + private static final String RANGE_CHECK = "range_check"; + + private TestRTMAfterNonRTMDeopt() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMAfterDeopt(false, false); + verifyRTMAfterDeopt(true, false); + + verifyRTMAfterDeopt(false, true); + verifyRTMAfterDeopt(true, true); + } + + private void verifyRTMAfterDeopt(boolean useStackLock, + boolean useRTMDeopt) throws Throwable { + CompilableTest test = new Test(); + String logFile = String.format("rtm_%s_stack_lock_%s_deopt.xml", + (useStackLock ? "use" : "no"), (useRTMDeopt ? "use" : "no")); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFile, + test, + "-XX:CompileThreshold=1", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", + useRTMDeopt), + "-XX:RTMAbortRatio=100", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD / 2L), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int traps = RTMTestBase.firedRTMStateChangeTraps(logFile); + + if (useRTMDeopt) { + Asserts.assertEQ(traps, 2, "Two uncommon traps with " + + "reason rtm_state_change should be fired."); + } else { + Asserts.assertEQ(traps, 0, "No uncommon traps with " + + "reason rtm_state_change should be fired."); + } + + int rangeCheckTraps = RTMTestBase.firedUncommonTraps(logFile, + TestRTMAfterNonRTMDeopt.RANGE_CHECK); + + Asserts.assertEQ(rangeCheckTraps, 1, + "One range_check uncommon trap should be fired."); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + int expectedStatEntries = (useRTMDeopt ? 4 : 2); + + Asserts.assertEQ(statistics.size(), expectedStatEntries, + String.format("VM output should contain %d RTM locking " + + "statistics entries.", expectedStatEntries)); + } + + public static class Test implements CompilableTest { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int ITERATIONS = 10000; + private static final int RANGE_CHECK_AT = ITERATIONS / 2; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::forceAbort" + }; + } + + public void forceAbort(int a[], boolean abort) { + try { + synchronized(monitor) { + a[0]++; + if (abort) { + Test.field = Test.UNSAFE.addressSize(); + } + } + } catch (Throwable t) { + // suppress any throwables + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + + int tmp[] = new int[1]; + + for (int i = 0; i < Test.ITERATIONS; i++ ) { + if (i == Test.RANGE_CHECK_AT) { + t.forceAbort(new int[0], false); + } else { + boolean isThreshold + = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD); + boolean isThresholdPlusRange + = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD + + Test.RANGE_CHECK_AT); + t.forceAbort(tmp, isThreshold || isThresholdPlusRange); + } + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMAfterNonRTMDeopt().test(); + } +} + diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that on high abort ratio method will be recompiled + * without rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMDeoptOnHighAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMDeoptOnHighAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that on high abort ratio method wil be deoptimized with + * rtm_state_change reason and after that RTM-based lock elision will not + * be used for that method. + * This test make asserts on total locks count done by compiled method, + * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. + * For more details on that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMDeoptOnHighAbortRatio extends CommandLineOptionTest { + private static final long ABORT_THRESHOLD + = AbortProvoker.DEFAULT_ITERATIONS / 2L; + + private TestRTMDeoptOnHighAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyDeopt(false); + verifyDeopt(true); + } + + private void verifyDeopt(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:RTMRetryCount=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD), + "-XX:RTMAbortRatio=100", + "-XX:CompileThreshold=1", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 1, "Expected to get only one " + + "deoptimization due to rtm state change"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + provoker.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalLocks(), + TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD, + "After AbortThreshold was reached, method should be" + + " recompiled without rtm lock eliding."); + } + + public static void main(String args[]) throws Throwable { + new TestRTMDeoptOnHighAbortRatio().test(); + } +} + diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that on low abort ratio method will be recompiled. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMDeoptOnLowAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMDeoptOnLowAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that low abort ratio method will be deoptimized with + * rtm_state_change reason and will continue to use RTM-based lock + * elision after that. + * This test make asserts on total locks count done by compiled method, + * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. + * For more details on that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { + private static final long LOCKING_THRESHOLD = 100L; + + private TestRTMDeoptOnLowAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMDeopt(false); + verifyRTMDeopt(true); + } + + private void verifyRTMDeopt(boolean useStackLock) throws Throwable { + CompilableTest test = new Test(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + useStackLock ? "use" : "no"); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + test, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD), + "-XX:RTMAbortThreshold=1", + "-XX:RTMAbortRatio=100", + "-XX:CompileThreshold=1", + "-XX:RTMRetryCount=0", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 1, + "Expected to get only one deoptimization due to rtm" + + " state change"); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, + "VM output should contain two RTM locking " + + "statistics entries for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics statisticsBeforeDeopt = null; + + for (RTMLockingStatistics s : statistics) { + if (s.getTotalLocks() + == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD + 1L) { + Asserts.assertNull(statisticsBeforeDeopt, + "Only one abort was expected during test run"); + statisticsBeforeDeopt = s; + } + } + + Asserts.assertNotNull(statisticsBeforeDeopt, + "After LockThreshold was reached, method should be recompiled " + + "with rtm lock eliding."); + } + + public static class Test implements CompilableTest { + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::addressSize" + }; + } + + public void forceAbort(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + t.forceAbort( + i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMDeoptOnLowAbortRatio().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMLockingCalculationDelay affect when + * abort ratio calculation is started. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMLockingCalculationDelay + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMLockingCalculationDelay + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that abort ratio calculation could be delayed using + * RTMLockingCalculationDelay option. + */ +public class TestRTMLockingCalculationDelay extends CommandLineOptionTest { + private static final boolean INFLATE_MONITOR = true; + + private TestRTMLockingCalculationDelay() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + // verify that calculation will be started immediately + verifyLockingCalculationDelay(0, 0, true); + + // verify that calculation will not be started during + // first 10 minutes, while test will be started immediately + verifyLockingCalculationDelay(600000, 0, false); + + // verify that calculation will be started after a second + verifyLockingCalculationDelay(1000, 1000, true); + } + + private void verifyLockingCalculationDelay(long delay, long testDelay, + boolean deoptExpected) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_delay_%d_%d.xml", delay, + testDelay); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareNumericFlag( + "RTMLockingCalculationDelay", delay), + "-XX:RTMAbortRatio=0", + "-XX:RTMAbortThreshold=0", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString( + TestRTMLockingCalculationDelay.INFLATE_MONITOR), + Long.toString(AbortProvoker.DEFAULT_ITERATIONS), + Long.toString(testDelay) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int deopts = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + if (deoptExpected) { + Asserts.assertGT(deopts, 0, "At least one deoptimization due to " + + "rtm_state_chage is expected"); + } else { + Asserts.assertEQ(deopts, 0, "No deoptimizations due to " + + "rtm_state_chage are expected"); + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingCalculationDelay().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMLockingThreshold affects rtm state transition + * ProfileRTM => UseRTM. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMLockingThreshold + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMLockingThreshold + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that RTMLockingThreshold option actually affects how soon + * method will be deoptimized on low abort ratio. + */ +public class TestRTMLockingThreshold extends CommandLineOptionTest { + private TestRTMLockingThreshold() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + /** + * We use non-zero abort threshold to avoid abort related to + * interrupts, VMM calls, etc. during first lock attempt. + * + */ + private static final int ABORT_THRESHOLD = 10; + + @Override + protected void runTestCases() throws Throwable { + verifyLockingThreshold(0, false); + verifyLockingThreshold(100, false); + verifyLockingThreshold(1000, false); + + verifyLockingThreshold(0, true); + verifyLockingThreshold(100, true); + verifyLockingThreshold(1000, true); + } + + private void verifyLockingThreshold(int lockingThreshold, + boolean useStackLock) throws Throwable { + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + "-XX:CompileThreshold=1", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:+UseRTMDeopt", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMLockingThreshold.ABORT_THRESHOLD), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + lockingThreshold), + "-XX:RTMAbortRatio=100", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock), + Integer.toString(lockingThreshold) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, "VM output should contain two " + + "RTM locking statistics entries."); + + /** + * We force abort on each odd iteration, so if RTMLockingThreshold==0, + * then we have to make 1 call without abort to avoid rtm state + * transition to NoRTM (otherwise actual abort ratio will be 100%), + * and after that make 1 call with abort to force deoptimization. + * This leads us to two locks for threshold 0. + * For other threshold values we have to make RTMLockingThreshold + 1 + * locks if locking threshold is even, or + 0 if odd. + */ + long expectedValue = lockingThreshold + + (lockingThreshold == 0L ? 2L : lockingThreshold % 2L); + + RTMLockingStatistics statBeforeDeopt = null; + for (RTMLockingStatistics s : statistics) { + if (s.getTotalLocks() == expectedValue) { + Asserts.assertNull(statBeforeDeopt, + "Only one statistics entry should contain aborts"); + statBeforeDeopt = s; + } + } + + Asserts.assertNotNull(statBeforeDeopt, "There should be exactly one " + + "statistics entry corresponding to ProfileRTM state."); + } + + public static class Test implements CompilableTest { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int TOTAL_ITERATIONS = 10000; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::addressSize" + }; + } + + public void lock(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.field += Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + t.lock(i % 2 == 1); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingThreshold().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMRetryCount affects actual amount of retries. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMRetryCount + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMRetryCount + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTMRetryCount option actually affects amount of + * retries on lock busy. + */ +public class TestRTMRetryCount extends CommandLineOptionTest { + /** + * Time in ms, during which busy lock will be locked. + */ + private static final int LOCKING_TIME = 5000; + private static final boolean INFLATE_MONITOR = true; + + private TestRTMRetryCount() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMRetryCount(0); + verifyRTMRetryCount(1); + verifyRTMRetryCount(5); + verifyRTMRetryCount(10); + } + + private void verifyRTMRetryCount(int retryCount) throws Throwable { + CompilableTest busyLock = new BusyLock(); + long expectedAborts = retryCount + 1L; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + busyLock, + "-XX:-UseRTMXendForLockBusy", + "-XX:RTMTotalCountIncrRate=1", + CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", + retryCount), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(TestRTMRetryCount.INFLATE_MONITOR), + Integer.toString(TestRTMRetryCount.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + busyLock.getMethodWithLockName(), outputAnalyzer.getStdout()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one rtm locking statistics entry for method " + + busyLock.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalAborts(), expectedAborts, + String.format("It is expected to get %d aborts", + expectedAborts)); + } + + public static void main(String args[]) throws Throwable { + new TestRTMRetryCount().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMSpinLoopCount affects time spent + * between locking attempts. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMSpinLoopCount + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMSpinLoopCount + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTMSpinLoopCount increase time spent between retries + * by comparing amount of retries done with different RTMSpinLoopCount's values. + */ +public class TestRTMSpinLoopCount extends CommandLineOptionTest { + private static final int LOCKING_TIME = 1000; + private static final int RTM_RETRY_COUNT = 1000; + private static final boolean INFLATE_MONITOR = true; + private static final long MAX_ABORTS = RTM_RETRY_COUNT + 1L; + private static final int[] SPIN_LOOP_COUNTS + = new int[] { 0, 100, 1_000, 1_000_000, 10_000_000 }; + + private TestRTMSpinLoopCount() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + long[] aborts = new long[TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length]; + for (int i = 0; i < TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length; i++) { + aborts[i] = getAbortsCountOnLockBusy( + TestRTMSpinLoopCount.SPIN_LOOP_COUNTS[i]); + } + + for (int i = 1; i < aborts.length; i++) { + Asserts.assertLTE(aborts[i], aborts[i - 1], "Increased spin loop " + + "count should not increase retries count."); + } + } + + private long getAbortsCountOnLockBusy(int spinLoopCount) throws Throwable { + CompilableTest test = new BusyLock(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", + TestRTMSpinLoopCount.RTM_RETRY_COUNT), + CommandLineOptionTest.prepareNumericFlag("RTMSpinLoopCount", + spinLoopCount), + "-XX:-UseRTMXendForLockBusy", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(TestRTMSpinLoopCount.INFLATE_MONITOR), + Integer.toString(TestRTMSpinLoopCount.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one entry for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertLTE(lock.getTotalAborts(), + TestRTMSpinLoopCount.MAX_ABORTS, String.format("Total aborts " + + "count (%d) should be less or equal to %d", + lock.getTotalAborts(), + TestRTMSpinLoopCount.MAX_ABORTS)); + + return lock.getTotalAborts(); + } + + public static void main(String args[]) throws Throwable { + new TestRTMSpinLoopCount().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that RTMTotalCountIncrRate option affects + * RTM locking statistics. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRate + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that with RTMTotalCountIncrRate=1 RTM locking statistics + * contains precise information abort attempted locks and that with other values + * statistics contains information abort non-zero locking attempts. + * Since assert done for RTMTotalCountIncrRate=1 is pretty strict, test uses + * -XX:RTMRetryCount=0 to avoid issue with retriable aborts. For more details on + * that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { + private TestRTMTotalCountIncrRate() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyLocksCount(1, false); + verifyLocksCount(64, false); + verifyLocksCount(128, false); + verifyLocksCount(1, true); + verifyLocksCount(64, true); + verifyLocksCount(128, true); + } + + private void verifyLocksCount(int incrRate, boolean useStackLock) + throws Throwable{ + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareNumericFlag( + "RTMTotalCountIncrRate", incrRate), + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + if (incrRate == 1) { + Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS, + "Total locks should be exactly the same as amount of " + + "iterations."); + } else { + Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM statistics " + + "should contain information for at least on lock."); + } + } + + public static class Test implements CompilableTest { + private static final long TOTAL_ITERATIONS = 10000L; + private final Object monitor = new Object(); + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName() + }; + } + + public void lock() { + synchronized(monitor) { + Test.field++; + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test test = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(test.monitor); + } + for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { + test.lock(); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRate().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that rtm locking is used for stack locks before + * inflation and after it used for inflated locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMAfterLockInflation + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMAfterLockInflation + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM is used after lock inflation by executing compiled + * method with RTM-based lock elision using stack lock first, then that lock + * is inflated and the same compiled method invoked again. + * + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before + * lock inflation and the same amount of times after inflation. + * As a result total locks count should be equal to + * {@code 2*AbortProvoker.DEFAULT_ITERATIONS}. + * It is a pretty strict assertion which could fail if some retriable abort + * happened: it could be {@code AbortType.RETRIABLE} or + * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these + * reasons simultaneously. In order to avoid false negative failures related + * to incorrect aborts counting, -XX:RTMRetryCount=0 is used. + */ +public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { + private static final long EXPECTED_LOCKS + = 2L * AbortProvoker.DEFAULT_ITERATIONS; + + private TestUseRTMAfterLockInflation() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + long totalLocksCount = 0; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + AbortType.XABORT.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, + "VM output should contain two rtm locking statistics entries " + + "for method " + provoker.getMethodWithLockName()); + + for (RTMLockingStatistics s : statistics) { + totalLocksCount += s.getTotalLocks(); + } + + Asserts.assertEQ(totalLocksCount, + TestUseRTMAfterLockInflation.EXPECTED_LOCKS, + "Total lock count should be greater or equal to " + + TestUseRTMAfterLockInflation.EXPECTED_LOCKS); + } + + public static class Test { + + /** + * Usage: + * Test <provoker type> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGT(args.length, 0, + "AbortType name is expected as first argument."); + + AbortProvoker provoker + = AbortType.lookup(Integer.valueOf(args[0])).provoker(); + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + provoker.forceAbort(); + } + provoker.inflateMonitor(); + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + provoker.forceAbort(); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMAfterLockInflation().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that UseRTMDeopt affects uncommon trap installation in + * copmpiled methods with synchronized block. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMDeopt + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeopt + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that usage of UseRTMDeopt option affects uncommon traps usage + * for methods that use locking. + */ +public class TestUseRTMDeopt extends CommandLineOptionTest { + private TestUseRTMDeopt() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyUseRTMDeopt(false); + verifyUseRTMDeopt(true); + } + + private void verifyUseRTMDeopt(boolean useRTMDeopt) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_%s_deopt.xml", + useRTMDeopt ? "use" : "no"); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", + useRTMDeopt), + AbortProvoker.class.getName(), + AbortType.XABORT.toString() + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int expectedUncommonTraps = useRTMDeopt ? 1 : 0; + int installedUncommonTraps + = RTMTestBase.installedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(expectedUncommonTraps, installedUncommonTraps, + String.format("Expected to find %d uncommon traps " + + "installed with reason rtm_state_change.", + expectedUncommonTraps)); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeopt().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that rtm locking is used for inflated locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForInflatedLocks + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMForInflatedLocks + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM-based lock elision could be used for inflated locks + * by calling compiled method that use RTM-based lock elision and using + * manually inflated lock. + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, + * so total locks count should be the same. + * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 + * is used. For more information abort that issue see + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMForInflatedLocks extends CommandLineOptionTest { + private TestUseRTMForInflatedLocks() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + RTMLockingStatistics lock; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:-UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one rtm locking statistics " + + "entry for method " + provoker.getMethodWithLockName()); + + lock = statistics.get(0); + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Total lock count should be greater or equal to " + + AbortProvoker.DEFAULT_ITERATIONS); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForInflatedLocks().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that rtm locking is used for stack locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocks + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMForStackLocks + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM-based lock elision could be used for stack locks + * by calling compiled method that use RTM-based lock elision and using + * stack lock. + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, + * so total locks count should be the same. + * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 + * is used. For more information abort that issue see + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMForStackLocks extends CommandLineOptionTest { + private static final boolean INFLATE_MONITOR = false; + + private TestUseRTMForStackLocks() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + RTMLockingStatistics lock; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(TestUseRTMForStackLocks.INFLATE_MONITOR)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one rtm locking statistics " + + "entry for method " + provoker.getMethodWithLockName()); + + lock = statistics.get(0); + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Total locks count should be greater or equal to " + + AbortProvoker.DEFAULT_ITERATIONS); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocks().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that UseRTMXendForLockBusy option affects + * method behaviour if lock is busy. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMXendForLockBusy + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMXendForLockBusy + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that with +UseRTMXendForLockBusy there will be no aborts + * forced by the test. + */ +public class TestUseRTMXendForLockBusy extends CommandLineOptionTest { + private final static int LOCKING_TIME = 5000; + + private TestUseRTMXendForLockBusy() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + // inflated lock, xabort on lock busy + verifyXendForLockBusy(true, false); + // inflated lock, xend on lock busy + verifyXendForLockBusy(true, true); + // stack lock, xabort on lock busy + verifyXendForLockBusy(false, false); + // stack lock, xend on lock busy + verifyXendForLockBusy(false, true); + } + + private void verifyXendForLockBusy(boolean inflateMonitor, + boolean useXend) throws Throwable { + CompilableTest test = new BusyLock(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + inflateMonitor), + CommandLineOptionTest.prepareBooleanFlag( + "UseRTMXendForLockBusy", + useXend), + "-XX:RTMRetryCount=0", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(inflateMonitor), + Integer.toString(TestUseRTMXendForLockBusy.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one rtm locking statistics entry for method " + + test.getMethodWithLockName()); + + long aborts = statistics.get(0).getAborts(AbortType.XABORT); + + if (useXend) { + Asserts.assertEQ(aborts, 0L, + "Expected to get no aborts on busy lock"); + } else { + Asserts.assertGT(aborts, 0L, + "Expected to get at least one abort on busy lock"); + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMXendForLockBusy().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that NoRTMLockEliding option could be applied to + * specified method and that such method will not use rtm. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestNoRTMLockElidingOption + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestNoRTMLockElidingOption + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that method tagged with option NoRTMLockElidingOption + * will not use RTM-based lock elision. + * Test invokes compiled method and checks that no deoptimization with + * rtm_state_change reason had happened and that that VM output + * does not contain RTM locking statistics for compiled method. + */ +public class TestNoRTMLockElidingOption extends CommandLineOptionTest { + private TestNoRTMLockElidingOption() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyOption(false); + verifyOption(true); + } + + public void verifyOption(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + String methodOption = String.format("-XX:CompileCommand=option," + + "%s,NoRTMLockEliding", provoker.getMethodWithLockName()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + methodOption, + "-XX:RTMTotalCountIncrRate=1", + "-XX:+UseRTMDeopt", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 0, + "No deoptimizations with rtm_state_change reason are expected"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 0, + "VM output should not contain RTM locking statistics entries " + + "for method " + provoker.getMethodWithLockName()); + } + + public static void main(String args[]) throws Throwable { + new TestNoRTMLockElidingOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that UseRTMLockEliding option could be applied to + * specified method and that such method will not be deoptimized + * on high abort ratio. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockElidingOption + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockElidingOption + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that method tagged with option UseRTMLockElidingOption + * will use RTM-based lock elision, but will be never deoptimized with + * rtm_state_change reason. + * Test invokes compiled method and checks that no deoptimization with + * rtm_state_change reason had happened and that that VM output + * contains RTM locking statistics for compiled method and that total locks + * count equals to method's invocations. + * Since last assert is pretty strict, test uses -XX:RTMRetryCount=0 in order + * to avoid issue with retriable aborts described in + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMLockElidingOption extends CommandLineOptionTest { + private TestUseRTMLockElidingOption() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyOption(false); + verifyOption(true); + } + + public void verifyOption(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + String methodOption = String.format("-XX:CompileCommand=option," + + "%s,UseRTMLockEliding", provoker.getMethodWithLockName()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + methodOption, + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+UseRTMDeopt", + "-XX:+PrintPreciseRTMLockingStatistics", + provoker.getClass().getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 0, + "Method deoptimization with rtm_state_change is unexpected"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one RTM locking " + + "statistics entry for method " + + provoker.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Expected to get total locks count equal to total amount of " + + "lock attempts."); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockElidingOption().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, 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 8031320 + * @summary Verify that rtm locking statistics contain proper information + * on overall aborts and locks count and count of aborts of + * different types. Test also verify that VM output does not + * contain rtm locking statistics when it should not. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatistics + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestPrintPreciseRTMLockingStatistics + */ + +import java.util.*; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that VM output does not contain RTM locking statistics when it + * should not (when PrintPreciseRTMLockingStatistics is off) and that with + * -XX:+PrintPreciseRTMLockingStatistics locking statistics contains sane + * total locks and aborts count as well as for specific abort types. + */ +public class TestPrintPreciseRTMLockingStatistics + extends CommandLineOptionTest { + private TestPrintPreciseRTMLockingStatistics() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyNoStatistics(); + verifyStatistics(); + } + + // verify that VM output does not contain + // rtm locking statistics + private void verifyNoStatistics() throws Throwable { + verifyNoStatistics(AbortType.XABORT); + + verifyNoStatistics(AbortType.XABORT, + "-XX:-PrintPreciseRTMLockingStatistics"); + + verifyNoStatistics(AbortType.XABORT, "-XX:-UseRTMLocking", + "-XX:+PrintPreciseRTMLockingStatistics"); + } + + // verify that rtm locking statistics contain information + // about each type of aborts + private void verifyStatistics() throws Throwable { + verifyAbortsCount(AbortType.XABORT); + verifyAbortsCount(AbortType.MEM_CONFLICT); + verifyAbortsCount(AbortType.BUF_OVERFLOW); + verifyAbortsCount(AbortType.NESTED_ABORT); + } + + private void verifyNoStatistics(AbortType abortProvokerType, + String... vmOpts) throws Throwable { + AbortProvoker provoker = abortProvokerType.provoker(); + List finalVMOpts = new LinkedList<>(); + Collections.addAll(finalVMOpts, vmOpts); + Collections.addAll(finalVMOpts, AbortProvoker.class.getName(), + abortProvokerType.toString()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(provoker, + finalVMOpts.toArray(new String[finalVMOpts.size()])); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 0, "VM output should not contain " + + "any RTM locking statistics"); + } + + private void verifyAbortsCount(AbortType abortType) throws Throwable { + AbortProvoker provoker = abortType.provoker(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + abortType.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(),outputAnalyzer.getOutput()); + + Asserts.assertGT(statistics.size(), 0, "VM output should contain one " + + "rtm locking statistics entry for method " + + provoker.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM locking statistics " + + "should contain non zero total locks count"); + + Asserts.assertGT(lock.getTotalAborts(), 0L, + "RTM locking statistics should contain non zero total aborts " + + "count"); + + Asserts.assertGT(lock.getAborts(abortType), 0L, String.format( + "RTM locking statistics should contain non zero aborts count " + + "for abort reason %s", abortType)); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatistics().test(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.Objects; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +/** + * Base class for different transactional execution abortion + * provokers aimed to force abort due to specified reason. + */ +public abstract class AbortProvoker implements CompilableTest { + public static final long DEFAULT_ITERATIONS = 10000L; + /** + * Inflates monitor associated with object {@code monitor}. + * Inflation is forced by entering the same monitor from + * two different threads. + * + * @param monitor monitor to be inflated. + * @return inflated monitor. + * @throws Exception if something went wrong. + */ + public static Object inflateMonitor(Object monitor) throws Exception { + Unsafe unsafe = Utils.getUnsafe(); + CyclicBarrier barrier = new CyclicBarrier(2); + + Runnable inflatingRunnable = () -> { + unsafe.monitorEnter(monitor); + try { + barrier.await(); + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException( + "Synchronization issue occurred.", e); + } finally { + unsafe.monitorExit(monitor); + } + }; + + Thread t = new Thread(inflatingRunnable); + t.start(); + // Wait until thread t enters the monitor. + barrier.await(); + // At this point monitor will be owned by thread t, + // so our attempt to enter the same monitor will force + // monitor inflation. + Asserts.assertFalse(unsafe.tryMonitorEnter(monitor), + "Not supposed to enter the monitor first"); + barrier.await(); + t.join(); + return monitor; + } + + + /** + * Get instance of specified AbortProvoker, inflate associated monitor + * if needed and then invoke forceAbort method in a loop. + * + * Usage: + * AbortProvoker <AbortType name> [<inflate monitor> + * [<iterations> [ <delay>]]] + * + * Default parameters are: + *
    + *
  • inflate monitor = true
  • + *
  • iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}
  • + *
  • delay = 0
  • + *
+ */ + public static void main(String args[]) throws Throwable { + Asserts.assertGT(args.length, 0, "At least one argument is required."); + + AbortType abortType = AbortType.lookup(Integer.valueOf(args[0])); + boolean monitorShouldBeInflated = true; + long iterations = AbortProvoker.DEFAULT_ITERATIONS; + + if (args.length > 1) { + monitorShouldBeInflated = Boolean.valueOf(args[1]); + + if (args.length > 2) { + iterations = Long.valueOf(args[2]); + + if (args.length > 3) { + Thread.sleep(Integer.valueOf(args[3])); + } + } + } + + AbortProvoker provoker = abortType.provoker(); + + if (monitorShouldBeInflated) { + provoker.inflateMonitor(); + } + + for (long i = 0; i < iterations; i++) { + provoker.forceAbort(); + } + } + + protected final Object monitor; + + protected AbortProvoker() { + this(new Object()); + } + + protected AbortProvoker(Object monitor) { + this.monitor = Objects.requireNonNull(monitor); + } + + /** + * Inflates monitor used by this AbortProvoker instance. + * @throws Exception + */ + public void inflateMonitor() throws Exception { + AbortProvoker.inflateMonitor(monitor); + } + + /** + * Forces transactional execution abortion. + */ + public abstract void forceAbort(); + + /** + * Returns names of all methods that have to be compiled + * in order to successfully force transactional execution + * abortion. + * + * @return array with methods' names that have to be compiled. + */ + @Override + public String[] getMethodsToCompileNames() { + return new String[] { getMethodWithLockName() }; + } + + /** + * Returns name of the method that will contain monitor whose locking + * will be elided using transactional execution. + * + * @return name of the method that will contain elided lock. + */ + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/AbortType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/AbortType.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Asserts; + +import java.util.HashMap; +import java.util.Map; + +/** + * Type of transactional execution abort. + * For more details on different abort types please see + * shared/vm/runtime/rtmLocking.hpp + */ +public enum AbortType { + XABORT(0), + RETRIABLE(1), + MEM_CONFLICT(2), + BUF_OVERFLOW(3), + DEBUG_BREAKPOINT(4), + NESTED_ABORT(5); + + private final int type; + private static final Map LOOKUP_MAP = new HashMap<>(); + + static { + for (AbortType abortType : AbortType.values()) { + Asserts.assertFalse(LOOKUP_MAP.containsKey(abortType.type), + "Abort type values should be unique."); + LOOKUP_MAP.put(abortType.type, abortType); + } + } + + private AbortType(int type) { + this.type = type; + } + + /** + * Returns AbortProvoker for aborts represented by this abort type. + * + * @return an AbortProvoker instance + */ + public AbortProvoker provoker() { + return AbortType.createNewProvoker(this); + } + + public static AbortType lookup(int type) { + Asserts.assertLT(type, AbortType.values().length, + "Unknown abort type."); + return LOOKUP_MAP.get(type); + } + + /** + * Returns transaction execution abort provoker for specified abortion type. + * + * @param type a type of abort which will be forced by returned + * AbortProvoker instance. + * @return AbortProvoker instance that will force abort of specified type + * @throws RuntimeException if there is no provoker for specified type + */ + private static AbortProvoker createNewProvoker(AbortType type) { + switch (type) { + case XABORT: + return new XAbortProvoker(); + case MEM_CONFLICT: + return new MemoryConflictProvoker(); + case BUF_OVERFLOW: + return new BufferOverflowProvoker(); + case NESTED_ABORT: + return new NestedAbortProvoker(); + default: + throw new RuntimeException("No provoker exists for type " + + type.name()); + } + } + + @Override + public String toString() { + return Integer.toString(type); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/BufferOverflowProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/BufferOverflowProvoker.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +/** + * In order to provoke transactional execution abort due to + * internal's buffer overflow BufferOverflowProvoker modifies + * 1MB of BYTES during single transaction. + */ +class BufferOverflowProvoker extends AbortProvoker { + /** + * To force buffer overflow abort we modify memory region with + * size more then L1d cache size. + */ + private static final int MORE_THAN_L1D_SIZE = 1024 * 1024; + private static final byte[] DATA = new byte[MORE_THAN_L1D_SIZE]; + + @Override + public void forceAbort() { + synchronized(monitor) { + for (int i = 0; i < BufferOverflowProvoker.DATA.length; i++) { + BufferOverflowProvoker.DATA[i]++; + } + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/BusyLock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +/** + * Test case for busy lock scenario. + * One thread enters the monitor and sleep for a while. + * Another thread is blocked on the same monitor. + */ +public class BusyLock implements CompilableTest, Runnable { + private static final int DEFAULT_TIMEOUT = 1000; + private final CyclicBarrier barrier; + + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + protected final Object monitor; + protected final int timeout; + + public BusyLock() { + this(BusyLock.DEFAULT_TIMEOUT); + } + + public BusyLock(int timeout) { + this.timeout = timeout; + this.monitor = new Object(); + this.barrier = new CyclicBarrier(2); + } + + @Override + public void run() { + try { + // wait until forceAbort leave monitor + barrier.await(); + if (UNSAFE.tryMonitorEnter(monitor)) { + try { + barrier.await(); + Thread.sleep(timeout); + } finally { + UNSAFE.monitorExit(monitor); + } + } else { + throw new RuntimeException("Monitor should be entered by " + + "::run() first."); + } + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException("Synchronization error happened.", e); + } + } + + public void test() { + try { + barrier.await(); + // wait until monitor is locked by a ::run method + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException("Synchronization error happened.", e); + } + synchronized(monitor) { + BusyLock.field++; + } + } + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::test"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { getMethodWithLockName() }; + } + + /** + * Usage: + * BusyLock [ <inflate monitor> [ <timeout> ] ] + * + * Default values are: + *
    + *
  • inflate monitor = {@code true}
  • + *
  • timeout = {@code BusyLock.DEFAULT_TIMEOUT}
  • + *
+ */ + public static void main(String args[]) throws Exception { + int timeoutValue = BusyLock.DEFAULT_TIMEOUT; + boolean inflateMonitor = true; + + if (args.length > 0 ) { + inflateMonitor = Boolean.valueOf(args[0]); + + if (args.length > 1) { + timeoutValue = Integer.valueOf(args[1]); + } + } + + BusyLock busyLock = new BusyLock(timeoutValue); + + if (inflateMonitor) { + AbortProvoker.inflateMonitor(busyLock.monitor); + } + + Thread t = new Thread(busyLock); + t.start(); + busyLock.test(); + t.join(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/CompilableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/CompilableTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +/** + * Interface for test scenarios that contain methods + * that should be compiled. + */ +public interface CompilableTest { + /** + * @return array with methods' names that should be compiled. + */ + String[] getMethodsToCompileNames(); + + /** + * @return name of method with RTM-elided lock. + */ + String getMethodWithLockName(); +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +/** + * To force transactional execution abort due to memory conflict + * one thread should access memory region from transactional region + * while another thread should modify the same memory region. + * Since this scenario is based on the race condition between threads + * you should not expect some particular amount of aborts. + */ +class MemoryConflictProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int INNER_ITERATIONS = 10000; + private final CyclicBarrier barrier; + /** + * This thread will access and modify memory region + * from outside of the transaction. + */ + private final Runnable conflictingThread; + + public MemoryConflictProvoker() { + this(new Object()); + } + + public MemoryConflictProvoker(Object monitor) { + super(monitor); + barrier = new CyclicBarrier(2); + conflictingThread = () -> { + try { + barrier.await(); + } catch (Exception e) { + throw new RuntimeException(e); + } + for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { + MemoryConflictProvoker.field++; + } + }; + } + + /** + * Accesses and modifies memory region from within the transaction. + */ + public void transactionalRegion() { + try { + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { + synchronized(monitor) { + MemoryConflictProvoker.field--; + } + } + } + + @Override + public void forceAbort() { + try { + Thread t = new Thread(conflictingThread); + t.start(); + transactionalRegion(); + t.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::transactionalRegion"; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/NestedAbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/NestedAbortProvoker.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.Arrays; + +/** + * In order to force nested transaction abort NestedAbortProvoker + * invoke BufferOverflowProvoker from transactional region. + */ +class NestedAbortProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private final AbortProvoker nestedAbortProvoker; + + public NestedAbortProvoker() { + this.nestedAbortProvoker = new XAbortProvoker(monitor); + } + + @Override + public void forceAbort() { + synchronized(monitor) { + NestedAbortProvoker.field++; + nestedAbortProvoker.forceAbort(); + NestedAbortProvoker.field--; + } + } + + @Override + public String[] getMethodsToCompileNames() { + String nestedProvokerMethods[] + = nestedAbortProvoker.getMethodsToCompileNames(); + String methods[] = Arrays.copyOf(nestedProvokerMethods, + nestedProvokerMethods.length + 1); + methods[methods.length - 1] = getMethodWithLockName(); + return methods; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/RTMLockingStatistics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/RTMLockingStatistics.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.EnumMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Wrapper for +UsePreciseRTMLockingStatistics output. + * + * Example of locking statistics: + * + * java/lang/ClassLoader.loadClass@7 + * # rtm locks total (estimated): 0 + * # rtm lock aborts : 13 + * # rtm lock aborts 0: 12 + * # rtm lock aborts 1: 0 + * # rtm lock aborts 2: 0 + * # rtm lock aborts 3: 0 + * # rtm lock aborts 4: 0 + * # rtm lock aborts 5: 0 + */ +public class RTMLockingStatistics { + /** + * Pattern for aborts per abort type entries. + */ + private static final Pattern ABORT_PATTERN; + + /** + * Pattern for whole statistics. + */ + private static final Pattern RTM_LOCKING_STATISTICS_PATTERN; + + static { + String abortRe + = "# rtm lock aborts\\s+(?[0-9]+):\\s(?[0-9]+)"; + + ABORT_PATTERN = Pattern.compile(abortRe); + RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile( + "(?[^.\n]+)\\." + + "(?[^@\n]+)@(?[0-9]+)\n" + + "# rtm locks total \\(estimated\\):\\s*" + + "(?[0-9]+)\n" + + "# rtm lock aborts\\s+:\\s*(?[0-9]+)\n" + + "(?(" + abortRe + "\n)+)"); + } + + private final long totalLocks; + private final long totalAborts; + private final String className; + private final String methodName; + private final int bci; + private final Map aborts = new EnumMap<>(AbortType.class); + + /** + * Constructs RTMLockingStatistics from matcher captured statistics entry. + * @param matcher Matcher captured statistics entry. + */ + private RTMLockingStatistics(Matcher matcher) { + className = matcher.group("className"); + methodName = matcher.group("methodName"); + bci = Integer.valueOf(matcher.group("bci")); + totalLocks = Long.valueOf(matcher.group("totalLocks")); + totalAborts = Long.valueOf(matcher.group("totalAborts")); + + Matcher abortMatcher = ABORT_PATTERN.matcher(matcher. + group("abortStats")); + + while (abortMatcher.find()) { + int type = Integer.valueOf(abortMatcher.group("type")); + long count = Long.valueOf(abortMatcher.group("count")); + setAborts(AbortType.lookup(type), count); + } + } + + + /** + * Parses string and return all founded RTM locking statistics entries. + * + * @param str the string to be parsed. + * @return list with all founded RTM locking statistics entries or + * empty list if nothing was found. + */ + public static List fromString(String str) { + List statistics = new LinkedList<>(); + Matcher matcher = RTM_LOCKING_STATISTICS_PATTERN.matcher(str); + + while (matcher.find()) { + RTMLockingStatistics lock = new RTMLockingStatistics(matcher); + statistics.add(lock); + } + + return statistics; + } + + /** + * Parses string and return all founded RTM locking statistics entries + * for locks in method {@code methodName}. + * + * @param methodName a name of the method for locks from which statistics + * should be gathered. + * @param str the string to be parsed. + * @return list with all founded RTM locking statistics entries or + * empty list if nothing was found. + */ + public static List fromString(String methodName, + String str) { + String formattedMethodName = formatMethodName(methodName); + + List statisticsForMethod = new LinkedList<>(); + for (RTMLockingStatistics statistics : fromString(str)) { + if (statistics.getLockName().startsWith(formattedMethodName)) { + statisticsForMethod.add(statistics); + } + } + return statisticsForMethod; + } + + /** + * Formats method's name so it will have the same format as + * in rtm locking statistics. + * + *
+     * Example:
+     * com/example/Klass::method => com/example/Klass.method
+     * com/example/Klass.method  => com/example/Klass.method
+     * com.example.Klass::method => com/example/Klass.method
+     * com.example.Klass.method  => com/example/Klass.method
+     * 
+ * + * @param methodName method's name that should be formatted. + * @return formatted method's name. + */ + private static String formatMethodName(String methodName) { + String m[]; + if (methodName.contains("::")) { + m = methodName.split("::"); + } else { + int splitAt = methodName.lastIndexOf('.'); + m = new String[2]; + m[0] = methodName.substring(0, splitAt); + m[1] = methodName.substring(splitAt + 1); + } + return String.format("%s.%s", m[0].replaceAll("\\.", "/"), m[1]); + } + + /** + * Returns name of lock for which this statistics was collected. + * Lock name has following format: + * <class name>.<method name>@<bci> + * + * @return name of lock. + */ + public String getLockName() { + return String.format("%s.%s@%d", className, methodName, bci); + } + + /** + * Returns aborts count for specified abort type. + * + * @param type an abort type. + * @return count of aborts. + */ + public long getAborts(AbortType type) { + return aborts.getOrDefault(type, 0L); + } + + /** + * Sets aborts count for specified abort type. + * + * @param type an abort type. + * @param count count of aborts. + */ + public void setAborts(AbortType type, long count) { + aborts.put(type, count); + } + + public long getTotalLocks() { + return totalLocks; + } + + public long getTotalAborts() { + return totalAborts; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getLockName()).append('\n'); + builder.append(String.format("# rtm locks total (estimated): %d\n", + getTotalLocks())); + builder.append(String.format("# rtm lock aborts: %d\n", + getTotalLocks())); + + for (AbortType type : AbortType.values()) { + builder.append(String.format("# rtm lock aborts %s %d\n", + type.toString(), getAborts(type))); + } + return builder.toString(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.LinkedList; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Utils; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; + +/** + * Auxiliary methods used for RTM testing. + */ +public class RTMTestBase { + private static final String RTM_STATE_CHANGE_REASON = "rtm_state_change"; + /** + * We don't parse compilation log as XML-document and use regular + * expressions instead, because in some cases it could be + * malformed. + */ + private static final String FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE + = "rtm_state_change + * installed during compilation. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @return count of installed uncommon traps with reason + * rtm_state_change. + * @throws IOException + */ + public static int installedRTMStateChangeTraps(String compilationLogFile) + throws IOException { + return RTMTestBase.installedUncommonTraps(compilationLogFile, + RTMTestBase.RTM_STATE_CHANGE_REASON); + } + + /** + * Finds count of fired uncommon traps with reason {@code reason}. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @param reason a reason of fired uncommon traps. + * @return count of fired uncommon traps with reason {@code reason}. + * @throws IOException + */ + public static int firedUncommonTraps(String compilationLogFile, + String reason) throws IOException { + String pattern = String.format( + RTMTestBase.FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE, + reason); + return RTMTestBase.findTraps(compilationLogFile, pattern); + } + + /** + * Finds count of fired uncommon traps with reason rtm_state_change. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @return count of fired uncommon traps with reason + * rtm_state_change. + * @throws IOException + */ + public static int firedRTMStateChangeTraps(String compilationLogFile) + throws IOException { + return RTMTestBase.firedUncommonTraps(compilationLogFile, + RTMTestBase.RTM_STATE_CHANGE_REASON); + } + + /** + * Finds count of uncommon traps that matches regular + * expression in {@code re}. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @param re regular expression to match uncommon traps. + * @throws IOException + */ + private static int findTraps(String compilationLogFile, String re) + throws IOException { + String compilationLog = RTMTestBase.fileAsString(compilationLogFile); + Pattern pattern = Pattern.compile(re); + Matcher matcher = pattern.matcher(compilationLog); + int traps = 0; + while (matcher.find()) { + traps++; + } + return traps; + } + + /** + * Returns file's content as a string. + * + * @param path a path to file to operate on. + * @return string with content of file. + * @throws IOException + */ + private static String fileAsString(String path) throws IOException { + byte[] fileAsBytes = Files.readAllBytes(Paths.get(path)); + return new String(fileAsBytes); + } + + /** + * Prepares VM options for test execution. + * This method get test java options, filter out all RTM-related options, + * adds CompileCommand=compileonly,method_name options for each method + * from {@code methodToCompile} and finally appends all {@code vmOpts}. + * + * @param test test case whose methods that should be compiled. + * If {@code null} then no additional compileonly + * commands will be added to VM options. + * @param vmOpts additional options to pass to VM. + * @return Array with VM options. + */ + private static String[] prepareTestOptions(CompilableTest test, + String... vmOpts) { + return RTMTestBase.prepareFilteredTestOptions(test, null, vmOpts); + } + + /** + * Prepares VM options for test execution. + * This method get test java options, filter out all RTM-related options + * and all options that matches regexps in {@code additionalFilters}, + * adds CompileCommand=compileonly,method_name options for each method + * from {@code methodToCompile} and finally appends all {@code vmOpts}. + * + * @param test test case whose methods that should be compiled. + * If {@code null} then no additional compileonly + * commands will be added to VM options. + * @param additionalFilters array with regular expression that will be + * used to filter out test java options. + * If {@code null} then no additional filters + * will be used. + * @param vmOpts additional options to pass to VM. + * @return array with VM options. + */ + private static String[] prepareFilteredTestOptions(CompilableTest test, + String[] additionalFilters, String... vmOpts) { + List finalVMOpts = new LinkedList<>(); + String[] filters; + + if (additionalFilters != null) { + filters = Arrays.copyOf(additionalFilters, + additionalFilters.length + 1); + } else { + filters = new String[1]; + } + + filters[filters.length - 1] = "RTM"; + String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); + Collections.addAll(finalVMOpts, filteredVMOpts); + Collections.addAll(finalVMOpts, "-Xcomp", "-server", + "-XX:-TieredCompilation", "-XX:+UseRTMLocking", + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + + if (test != null) { + for (String method : test.getMethodsToCompileNames()) { + finalVMOpts.add("-XX:CompileCommand=compileonly," + method); + } + } + Collections.addAll(finalVMOpts, vmOpts); + return finalVMOpts.toArray(new String[finalVMOpts.size()]); + } + + /** + * Adds additional options for VM required for successful execution of test. + * + * @param logFileName a name of compilation log file + * @param test a test case to execute + * @param options additional options to VM + * @return an array with VM options + */ + private static String[] prepareTestOptions(String logFileName, + CompilableTest test, String... options) { + String[] preparedOptions = RTMTestBase.prepareFilteredTestOptions( + test, + new String[] { + "LogCompilation", + "LogFile" + }); + List updatedOptions = new LinkedList<>(); + Collections.addAll(updatedOptions, preparedOptions); + Collections.addAll(updatedOptions, + "-XX:+LogCompilation", + "-XX:LogFile=" + logFileName); + Collections.addAll(updatedOptions, options); + + return updatedOptions.toArray(new String[updatedOptions.size()]); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +/** + * Current RTM locking implementation force transaction abort + * before native method call by explicit xabort(0) call. + */ +class XAbortProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + + public XAbortProvoker() { + this(new Object()); + } + + public XAbortProvoker(Object monitor) { + super(monitor); + } + + @Override + public void forceAbort() { + synchronized(monitor) { + XAbortProvoker.field = UNSAFE.addressSize(); + } + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + Unsafe.class.getName() + "::addressSize" + }; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm.predicate; + +import sun.hotspot.cpuinfo.CPUInfo; + +import java.util.function.BooleanSupplier; + +public class SupportedCPU implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return CPUInfo.hasFeature("rtm"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm.predicate; + +import com.oracle.java.testlibrary.Platform; + +import java.util.function.BooleanSupplier; + +public class SupportedVM implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return Platform.isServer() && !Platform.isEmbedded(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/CorrectnessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, 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 CorrectnessTest + * @bug 8038418 + * @library /testlibrary /testlibrary/whitebox + * @compile execution/TypeConflict.java execution/TypeProfile.java + * execution/MethodHandleDelegate.java + * @build CorrectnessTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest RETURN + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest PARAMETERS + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest ARGUMENTS + * @summary Tests correctness of type usage with type profiling and speculations + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; +import execution.Execution; +import execution.MethodHandleDelegate; +import execution.TypeConflict; +import execution.TypeProfile; +import hierarchies.*; +import scenarios.*; +import sun.hotspot.WhiteBox; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; + +public class CorrectnessTest { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + public static void main(String[] args) { + if (!Platform.isServer()) { + System.out.println("ALL TESTS SKIPPED"); + } + Asserts.assertGTE(args.length, 1); + ProfilingType profilingType = ProfilingType.valueOf(args[0]); + if (runTests(profilingType)) { + System.out.println("ALL TESTS PASSED"); + } else { + throw new RuntimeException("SOME TESTS FAILED"); + } + } + + @SuppressWarnings("unchecked") + public static boolean runTests(ProfilingType profilingType) { + boolean result = true; + + List executionList = new ArrayList<>(); + executionList.add(new TypeConflict()); + executionList.add(new TypeProfile()); + for (int i = 0, n = executionList.size(); i < n; i++) { + executionList.add(new MethodHandleDelegate(executionList.get(i))); + } + + List hierarchyList = new ArrayList<>(); + hierarchyList.add(new DefaultMethodInterface.Hierarchy()); + hierarchyList.add(new DefaultMethodInterface2.Hierarchy()); + hierarchyList.add(new Linear.Hierarchy()); + hierarchyList.add(new Linear2.Hierarchy()); + hierarchyList.add(new OneRank.Hierarchy()); + for (int i = 0, n = hierarchyList.size(); i < n; i++) { + hierarchyList.add(new NullableType(hierarchyList.get(i))); + } + + List>> testCasesConstructors + = new ArrayList<>(); + testCasesConstructors.add(ArrayCopy::new); + testCasesConstructors.add(ArrayReferenceStore::new); + testCasesConstructors.add(ClassIdentity::new); + testCasesConstructors.add(ClassInstanceOf::new); + testCasesConstructors.add(ClassIsInstance::new); + testCasesConstructors.add(ReceiverAtInvokes::new); + testCasesConstructors.add(CheckCast::new); + + for (TypeHierarchy hierarchy : hierarchyList) { + for (BiFunction> constructor : testCasesConstructors) { + for (Execution execution : executionList) { + Scenario scenario = constructor.apply(profilingType, hierarchy); + if (scenario.isApplicable()) { + result &= executeTest(hierarchy, execution, scenario); + } + } + } + } + return result; + } + + /** + * Executes test case + * + * @param hierarchy type hierarchy for the test + * @param execution execution scenario + * @param scenario test scenario executed with given Execution + */ + private static boolean executeTest(TypeHierarchy hierarchy, Execution execution, Scenario scenario) { + boolean testCaseResult = false; + String testName = hierarchy.getClass().getName() + " :: " + scenario.getName() + " @ " + execution.getName(); + clearAllMethodsState(scenario.getClass()); + try { + execution.execute(scenario); + testCaseResult = true; + } catch (Exception e) { + System.err.println(testName + " failed with exception " + e); + e.printStackTrace(); + } + System.out.println((testCaseResult ? "PASSED: " : "FAILED: ") + testName); + return testCaseResult; + } + + private static void clearAllMethodsState(Class aClass) { + while (aClass != null) { + for (Method m : aClass.getDeclaredMethods()) { + WHITE_BOX.clearMethodState(m); + } + aClass = aClass.getSuperclass(); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/OffTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/OffTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 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 CorrectnessTest + * @bug 8038418 + * @library /testlibrary /testlibrary/whitebox + * @compile execution/TypeConflict.java execution/TypeProfile.java + * execution/MethodHandleDelegate.java + * @build CorrectnessTest + * @build OffTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/timeout=1200 OffTest + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import scenarios.ProfilingType; + +import java.util.Random; + +public class OffTest { + private static final String[] OPTIONS = { + "-Xbootclasspath/a:.", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:CompileCommand=exclude,execution/*::methodNotToCompile", + "-XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType", + "", // -XX:TypeProfileLevel=? + "", // -XX:?UseTypeSpeculation + CorrectnessTest.class.getName(), + "", // ProfilingType.name() + }; + + private static final String TYPE_PROFILE_LEVEL = "TypeProfileLevel"; + private static final String USE_TYPE_SPECULATION = "UseTypeSpeculation"; + private static final int TYPE_PROFILE_LEVEL_LENGTH = 3; + private static final int TYPE_PROFILE_LEVEL_BOUND = 3; + private static final int DEFAULT_COUNT = 10; + private static final int PROFILING_TYPE_INDEX = OPTIONS.length - 1; + private static final int TYPE_PROFILE_INDEX = OPTIONS.length - 4; + private static final int USE_TYPE_SPECULATION_INDEX = OPTIONS.length - 3; + private static final Random RNG; + + static { + String str = System.getProperty("seed"); + long seed = str != null ? Long.parseLong(str) : new Random().nextLong(); + RNG = new Random(seed); + System.out.printf("-Dseed=%d%n", seed); + } + + public static void main(String[] args) throws Exception { + int count = DEFAULT_COUNT; + if (args.length > 0) { + count = Integer.parseInt(args[0]) ; + } + for (int i = 0; i < count; ++i) { + runTest(); + } + } + + private static void runTest() throws Exception { + String useTypeSpeculation = "-XX:" + (RNG.nextBoolean() ? "+" : "-") + USE_TYPE_SPECULATION; + String typeProfileLevel = "-XX:" + TYPE_PROFILE_LEVEL + "=" + randomTypeProfileLevel(); + ProfilingType type = randomProfileType(); + OPTIONS[TYPE_PROFILE_INDEX] = typeProfileLevel; + OPTIONS[USE_TYPE_SPECULATION_INDEX] = useTypeSpeculation; + OPTIONS[PROFILING_TYPE_INDEX] = type.name(); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(/* addTestVmOptions= */ true, OPTIONS); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(processBuilder.start()); + outputAnalyzer.shouldHaveExitValue(0); + } + + private static ProfilingType randomProfileType() { + ProfilingType[] value = ProfilingType.values(); + return value[RNG.nextInt(value.length)]; + } + + private static String randomTypeProfileLevel() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < TYPE_PROFILE_LEVEL_LENGTH; ++i) { + stringBuilder.append(RNG.nextInt(TYPE_PROFILE_LEVEL_BOUND)); + } + return stringBuilder.toString(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/execution/Execution.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/execution/Execution.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Execution scenario represents test methods execution type. + * @param parameter type + * @param result Type + */ +public interface Execution { + /** + * Executes the test code of the given scenario + * See {@link scenarios.Scenario#run(T)} + * + * @param scenario test scenario + */ + void execute(Scenario scenario); + + default String getName() { + return this.getClass().getName(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/execution/MethodHandleDelegate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/execution/MethodHandleDelegate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +/** + * Executes test scenario using {@link MethodHandle#invoke(Object...)}. + * Delegates execution to the given {@link Execution} by creating + * new test scenario, see {@link Scenario} + */ +public class MethodHandleDelegate implements Execution { + private final Execution delegate; + + public MethodHandleDelegate(Execution delegate) { + this.delegate = delegate; + } + + @Override + public void execute(Scenario scenario) { + delegate.execute(new MHScenario(scenario)); + } + + @Override + public String getName() { + return "MethodHandleDelegate # " + delegate.getName(); + } + + private static class MHScenario extends Scenario { + private final Scenario scenario; + private static final MethodHandle METHOD_HANDLE_RUN; + + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType methodType = MethodType.methodType(Object.class, TypeHierarchy.I.class); + + try { + METHOD_HANDLE_RUN = lookup.findVirtual(Scenario.class, "run", methodType); + } catch (NoSuchMethodException | IllegalAccessException e) { + System.err.println("Failed to get target method run() with " + e); + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + * Constructor + * + * @param scenario test scenario to be executed + */ + private MHScenario(Scenario scenario) { + super("MethodHandle::" + scenario.getName(), scenario.profilingType, scenario.hierarchy); + this.scenario = scenario; + } + + /** + * Runs {@link Scenario#run(T)} with {@link MethodHandle#invoke(Object...)} + * + * @param t subject of the test + * @return result of the underlying {@link Scenario#run(T)} invocation + */ + @SuppressWarnings("unchecked") + @Override + public R run(T t) { + try { + return (R) METHOD_HANDLE_RUN.invoke(scenario, t); + } catch (Throwable thr) { + System.err.println(scenario.getName() + + " failed to invoke target method run() with " + thr); + throw new RuntimeException("Invocation failed", thr); + } + } + + @Override + public void check(R r, T t) { + scenario.check(r, t); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/execution/TypeConflict.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/execution/TypeConflict.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Type profiling conflict execution scenario. The main goal is + * to make compiler profile and compile methods with different types. + * Scenario tests guards by passing conflicting types (incompatible + * for the profiled data). + */ +public class TypeConflict implements Execution { + /** Test methods execution number to make profile */ + private final static int POLLUTION_THRESHOLD = 5000; + /** Test methods execution number to make it profiled and compiled*/ + private final static int PROFILE_THRESHOLD = 20000; + + @Override + public void execute(Scenario scenario) { + T base = scenario.getProfiled(); + T incompatible = scenario.getConflict(); + + // pollute profile by passing different types + R baseResult = null; + R incResult = null; + for (int i = 0; i < POLLUTION_THRESHOLD; i++) { + baseResult = methodNotToCompile(scenario, base); + incResult = methodNotToCompile(scenario, incompatible); + } + scenario.check(baseResult, base); + scenario.check(incResult, incompatible); + + // profile and compile + R result = null; + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, base); + } + scenario.check(result, base); + + // pass another type to make guard work and recompile + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, incompatible); + } + scenario.check(result, incompatible); + } + + private R methodNotToCompile(Scenario scenario, T t) { + return scenario.run(t); + } +} + diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/execution/TypeProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/execution/TypeProfile.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Profile type execution scenario. Executes tester method + * in a loop without any manipulation with types or instances. + */ +public class TypeProfile implements Execution { + /** Number of test method execution to make it profiled and compiled */ + private final static int PROFILE_THRESHOLD = 100000; + + /** + * Makes scenario code be profiled and compiled + * @param scenario Test scenario + */ + @Override + public void execute(Scenario scenario) { + R result = null; + T prof = scenario.getProfiled(); + T confl = scenario.getConflict(); + + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, prof); + } + scenario.check(result, prof); + + result = methodNotToCompile(scenario, confl); + scenario.check(result, confl); + } + + protected R methodNotToCompile(Scenario scenario, T t) { + return scenario.run(t); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class DefaultMethodInterface { + private DefaultMethodInterface() { + } + + public static class Hierarchy + extends TypeHierarchy { + public Hierarchy() { + super(new DefaultMethodInterface.A(), new DefaultMethodInterface.B(), + DefaultMethodInterface.A.class, DefaultMethodInterface.B.class); + } + } + + public static interface I2 extends TypeHierarchy.I { + default int m() { + return TypeHierarchy.ANSWER; + } + } + + public static class A implements I2 { + // use default method from I2 + } + + public static class B extends A { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface2.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class DefaultMethodInterface2 { + private DefaultMethodInterface2() { + } + + public static class Hierarchy + extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new DefaultMethodInterface2.B(), + TypeHierarchy.A.class, DefaultMethodInterface2.B.class); + } + } + + public static interface I2 extends TypeHierarchy.I { + default int m() { + return TypeHierarchy.ANSWER; + } + } + + public static class B implements I2 { + // default method I2.m() + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/Linear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/Linear.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class Linear { + private Linear() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new Linear.B(), + TypeHierarchy.A.class, Linear.B.class); + } + } + + public static class B extends TypeHierarchy.A { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/Linear2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/Linear2.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class Linear2 { + private Linear2() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new A(), new Linear2.B(), + A.class, Linear2.B.class); + } + } + + public static interface I2 { + int m(); + } + + public static class B extends TypeHierarchy.A implements Linear2.I2 { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/NullableType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/NullableType.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class NullableType + extends TypeHierarchy { + + public NullableType(TypeHierarchy delegate) { + super(delegate.getM(), null, + delegate.getClassM(), delegate.getClassN()); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/OneRank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/OneRank.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class OneRank { + private OneRank() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new OneRank.B(), + TypeHierarchy.A.class, OneRank.B.class); + } + } + + public static class B implements TypeHierarchy.I { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } + +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/hierarchies/TypeHierarchy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/hierarchies/TypeHierarchy.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +/** + * Type hierarchy contains classes the type profiling and speculation are tested with + */ +public abstract class TypeHierarchy { + // Magic numbers + public static final int ANSWER = 42; + public static final int TEMP = 451; + public static final int YEAR = 1984; + + private final M m; + private final N n; + private final Class classM; + private final Class classN; + + protected TypeHierarchy(M m, N n, Class classM, Class classN) { + this.m = m; + this.n = n; + this.classM = classM; + this.classN = classN; + } + + public final M getM() { + return m; + } + + public final N getN() { + return n; + } + + public final Class getClassM() { + return classM; + } + + public final Class getClassN() { + return classN; + } + + public interface I { + int m(); + } + + public static class A implements I { + @Override + public int m() { + return TypeHierarchy.ANSWER; + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ArrayCopy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayCopy.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +import java.util.Arrays; + +/** + * Tests System.arraycopy() + */ +public class ArrayCopy extends ArrayScenario { + public ArrayCopy(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ArrayCopy", profilingType, hierarchy); + } + + /** + * @param obj is used to fill arrays + * @return the same obj + */ + @Override + public TypeHierarchy.I run(TypeHierarchy.I obj) { + switch (profilingType) { + case RETURN: + TypeHierarchy.I t = collectReturnType(obj); + Arrays.fill(array, t); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + case ARGUMENTS: + field = obj; + Arrays.fill(array, field); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + case PARAMETERS: + Arrays.fill(array, obj); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + } + throw new RuntimeException("Should not reach here"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ArrayReferenceStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayReferenceStore.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +import java.util.Arrays; + +/** + * Tests aastore bytecode + */ +public class ArrayReferenceStore extends ArrayScenario { + public ArrayReferenceStore(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ArrayReferenceStore", profilingType, hierarchy); + } + + /** + * @param obj is used to fill arrays + * @return obj + */ + @Override + public TypeHierarchy.I run(TypeHierarchy.I obj) { + switch (profilingType) { + case RETURN: + TypeHierarchy.I t = collectReturnType(obj); + Arrays.fill(array, t); + matrix[0] = array; + return matrix[0][0]; + case ARGUMENTS: + field = obj; + Arrays.fill(array, field); + matrix[0] = array; + return matrix[0][0]; + case PARAMETERS: + Arrays.fill(array, obj); + matrix[0] = array; + return matrix[0][0]; + } + throw new RuntimeException("Should not reach here"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ArrayScenario.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayScenario.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +import java.lang.reflect.Array; +import java.util.Arrays; + +/** + * Base class for array scenarios + */ +public abstract class ArrayScenario extends Scenario { + protected final TypeHierarchy.I[] array; + protected final TypeHierarchy.I[][] matrix; + + protected ArrayScenario(String name, ProfilingType profilingType, + TypeHierarchy hierarchy) { + super(name, profilingType, hierarchy); + final int x = 20; + final int y = 10; + + TypeHierarchy.I prof = hierarchy.getM(); + TypeHierarchy.I confl = hierarchy.getN(); + + this.array = (TypeHierarchy.I[]) Array.newInstance(hierarchy.getClassM(), y); + Arrays.fill(array, prof); + + this.matrix = (TypeHierarchy.I[][]) Array.newInstance(hierarchy.getClassM(), x, y); + for (int i = 0; i < x; i++) { + this.matrix[i] = this.array; + } + + Asserts.assertEquals(array.length, matrix[0].length, "Invariant"); + } + + @Override + public boolean isApplicable() { + return hierarchy.getClassM().isAssignableFrom(hierarchy.getClassN()); + } + + @Override + public void check(TypeHierarchy.I res, TypeHierarchy.I orig) { + Asserts.assertEquals(res, orig, "Check failed"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/CheckCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/CheckCast.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +import java.util.Objects; + +/** + * Checkcast scenario + * @param profiling parameter + */ +public class CheckCast extends Scenario { + public CheckCast(ProfilingType profilingType, TypeHierarchy hierarchy) { + super("CheckCast", profilingType, hierarchy); + } + + /** + * Returns type profiling. + * @param obj is a profiled parameter for the test + * @return parameter casted to the type R + */ + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t != null) { + return t.m(); + } + return null; + case ARGUMENTS: + field = obj; + if (field != null) { + return field.m(); + } + return null; + case PARAMETERS: + if (obj != null) { + return obj.m(); + } + return null; + } + throw new RuntimeException("Should not reach here"); + } + + @Override + public void check(Integer result, T orig) { + if (result != null || orig != null) { + Objects.requireNonNull(result); + Objects.requireNonNull(orig); + Asserts.assertEquals(result, orig.m(), "Results mismatch"); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ClassIdentity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ClassIdentity.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests pattern: if (a.getClass() == D.class) + */ +public class ClassIdentity extends Scenario { + public ClassIdentity(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassIdentity", profilingType, hierarchy); + } + + @Override + public boolean isApplicable() { + return hierarchy.getM() != null && hierarchy.getN() != null; + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t.getClass() == TypeHierarchy.A.class) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (field.getClass() == TypeHierarchy.A.class) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (obj.getClass() == TypeHierarchy.A.class) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (orig.getClass() == TypeHierarchy.A.class) { + Asserts.assertEquals(result, orig.m(), + "Results are not equal for TypeHierarchy.A.class"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ClassInstanceOf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ClassInstanceOf.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests instanceof + */ +public class ClassInstanceOf extends Scenario { + public ClassInstanceOf(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassInstanceOf", profilingType, hierarchy); + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t instanceof TypeHierarchy.A) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (field instanceof TypeHierarchy.A) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (obj instanceof TypeHierarchy.A) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (orig instanceof TypeHierarchy.A) { + Asserts.assertEquals(result, orig.m(), "Results are not equal for TypeHierarchy.A"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ClassIsInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ClassIsInstance.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests {@link Class#isInstance(Object)} + */ +public class ClassIsInstance extends Scenario { + private final Class baseClass; + + public ClassIsInstance(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassIsInstance", profilingType, hierarchy); + this.baseClass = hierarchy.getClassM(); + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (baseClass.isInstance(t)) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (baseClass.isInstance(field)) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (baseClass.isInstance(obj)) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (baseClass.isInstance(orig)) { + Asserts.assertEquals(result, orig.m(), "Results are not equal for base class"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ProfilingType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ProfilingType.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +public enum ProfilingType { + /** type profiling of return values of reference types from an invoke */ + RETURN, + /** type profiling for reference parameters on method entries */ + PARAMETERS, + /** type profiling for reference arguments at an invoke */ + ARGUMENTS, +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/ReceiverAtInvokes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/ReceiverAtInvokes.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Receiver at invokes profiling and speculation + * + * @param parameter to be returned + */ +public class ReceiverAtInvokes extends Scenario { + public ReceiverAtInvokes(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ReceiverAtInvokes", profilingType, hierarchy); + } + + @Override + public boolean isApplicable() { + return hierarchy.getM() != null && hierarchy.getN() != null; + } + + /** + * Receiver profiling + * + * @param obj is a profiled parameter for the test + * @return parameter casted to the type R + */ + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + return inlinee(t); + case ARGUMENTS: + field = obj; + return inlinee(field); + case PARAMETERS: + return inlinee(obj); + } + throw new RuntimeException("Should not reach here"); + } + + private Integer inlinee(T obj) { + return obj.m(); // should be inlined + } + + @Override + public void check(Integer result, T orig) { + Asserts.assertEquals(result, orig.m(), "Results mismatch"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/types/correctness/scenarios/Scenario.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/types/correctness/scenarios/Scenario.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +/** + * Test scenario + * + * @param parameter type + * @param result type + */ +public abstract class Scenario { + + private final String name; + public final ProfilingType profilingType; + public final TypeHierarchy hierarchy; + protected volatile T field; + + /** + * Constructor + * + * @param name scenario name + * @param profilingType tested profiling type + * @param hierarchy type hierarchy + */ + protected Scenario(String name, ProfilingType profilingType, + TypeHierarchy hierarchy) { + this.profilingType = profilingType; + this.name = name + " # " + profilingType.name(); + this.hierarchy = hierarchy; + } + + /** + * Returns the object which should be used as a parameter + * for the methods used for profile data + * + * @return profiled type object + */ + public T getProfiled() { + return hierarchy.getM(); + } + + /** + * Returns the object which makes a conflict for a profiled data + * when passed instead of {@linkplain Scenario#getProfiled} + * + * @return incompatible to profiled object + */ + public T getConflict() { + return hierarchy.getN(); + } + + /** + * @return scenario name + */ + public String getName() { + return name; + } + + /** Is this scenario applicable for a hierarchy it was constructed with */ + public boolean isApplicable() { + return true; + } + + /** + * Runs test scenario + * + * @param t subject of the test + * @return result of the test invocation + */ + public abstract R run(T t); + + /** Used for a return type profiling */ + protected final T collectReturnType(T t) { + return t; + } + + /** + * Checks the result for R and T + * + * @param r result + * @param t original + * @throws java.lang.RuntimeException on result mismatch + */ + public abstract void check(R r, T t); +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2013, 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 8032410 + * @summary Stack overflow at deoptimization doesn't release owned monitors + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangMonitorOwned::m1 -XX:CompileCommand=exclude,TestStackBangMonitorOwned::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangMonitorOwned + * + */ +public class TestStackBangMonitorOwned { + + static class UnloadedClass1 { + volatile int field; + } + + static Object m1(boolean deopt) { + long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, + l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, + l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36, + l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48, + l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, + l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72, + l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84, + l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96, + l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107, + l108, l109, l110, l111, l112, l113, l114, l115, l116, l117, + l118, l119, l120, l121, l122, l123, l124, l125, l126, l127, + l128, l129, l130, l131, l132, l133, l134, l135, l136, l137, + l138, l139, l140, l141, l142, l143, l144, l145, l146, l147, + l148, l149, l150, l151, l152, l153, l154, l155, l156, l157, + l158, l159, l160, l161, l162, l163, l164, l165, l166, l167, + l168, l169, l170, l171, l172, l173, l174, l175, l176, l177, + l178, l179, l180, l181, l182, l183, l184, l185, l186, l187, + l188, l189, l190, l191, l192, l193, l194, l195, l196, l197, + l198, l199, l200, l201, l202, l203, l204, l205, l206, l207, + l208, l209, l210, l211, l212, l213, l214, l215, l216, l217, + l218, l219, l220, l221, l222, l223, l224, l225, l226, l227, + l228, l229, l230, l231, l232, l233, l234, l235, l236, l237, + l238, l239, l240, l241, l242, l243, l244, l245, l246, l247, + l248, l249, l250, l251, l252, l253, l254, l255, l256, l257, + l258, l259, l260, l261, l262, l263, l264, l265, l266, l267, + l268, l269, l270, l271, l272, l273, l274, l275, l276, l277, + l278, l279, l280, l281, l282, l283, l284, l285, l286, l287, + l288, l289, l290, l291, l292, l293, l294, l295, l296, l297, + l298, l299, l300, l301, l302, l303, l304, l305, l306, l307, + l308, l309, l310, l311, l312, l313, l314, l315, l316, l317, + l318, l319, l320, l321, l322, l323, l324, l325, l326, l327, + l328, l329, l330, l331, l332, l333, l334, l335, l336, l337, + l338, l339, l340, l341, l342, l343, l344, l345, l346, l347, + l348, l349, l350, l351, l352, l353, l354, l355, l356, l357, + l358, l359, l360, l361, l362, l363, l364, l365, l366, l367, + l368, l369, l370, l371, l372, l373, l374, l375, l376, l377, + l378, l379, l380, l381, l382, l383, l384, l385, l386, l387, + l388, l389, l390, l391, l392, l393, l394, l395, l396, l397, + l398, l399, l400, l401, l402, l403, l404, l405, l406, l407, + l408, l409, l410, l411, l412, l413, l414, l415, l416, l417, + l418, l419, l420, l421, l422, l423, l424, l425, l426, l427, + l428, l429, l430, l431, l432, l433, l434, l435, l436, l437, + l438, l439, l440, l441, l442, l443, l444, l445, l446, l447, + l448, l449, l450, l451, l452, l453, l454, l455, l456, l457, + l458, l459, l460, l461, l462, l463, l464, l465, l466, l467, + l468, l469, l470, l471, l472, l473, l474, l475, l476, l477, + l478, l479, l480, l481, l482, l483, l484, l485, l486, l487, + l488, l489, l490, l491, l492, l493, l494, l495, l496, l497, + l498, l499, l500, l501, l502, l503, l504, l505, l506, l507, + l508, l509, l510, l511; + + long ll0, ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, ll9, ll10, ll11, ll12, + ll13, ll14, ll15, ll16, ll17, ll18, ll19, ll20, ll21, ll22, ll23, ll24, + ll25, ll26, ll27, ll28, ll29, ll30, ll31, ll32, ll33, ll34, ll35, ll36, + ll37, ll38, ll39, ll40, ll41, ll42, ll43, ll44, ll45, ll46, ll47, ll48, + ll49, ll50, ll51, ll52, ll53, ll54, ll55, ll56, ll57, ll58, ll59, ll60, + ll61, ll62, ll63, ll64, ll65, ll66, ll67, ll68, ll69, ll70, ll71, ll72, + ll73, ll74, ll75, ll76, ll77, ll78, ll79, ll80, ll81, ll82, ll83, ll84, + ll85, ll86, ll87, ll88, ll89, ll90, ll91, ll92, ll93, ll94, ll95, ll96, + ll97, ll98, ll99, ll100, ll101, ll102, ll103, ll104, ll105, ll106, ll107, + ll108, ll109, ll110, ll111, ll112, ll113, ll114, ll115, ll116, ll117, + ll118, ll119, ll120, ll121, ll122, ll123, ll124, ll125, ll126, ll127, + ll128, ll129, ll130, ll131, ll132, ll133, ll134, ll135, ll136, ll137, + ll138, ll139, ll140, ll141, ll142, ll143, ll144, ll145, ll146, ll147, + ll148, ll149, ll150, ll151, ll152, ll153, ll154, ll155, ll156, ll157, + ll158, ll159, ll160, ll161, ll162, ll163, ll164, ll165, ll166, ll167, + ll168, ll169, ll170, ll171, ll172, ll173, ll174, ll175, ll176, ll177, + ll178, ll179, ll180, ll181, ll182, ll183, ll184, ll185, ll186, ll187, + ll188, ll189, ll190, ll191, ll192, ll193, ll194, ll195, ll196, ll197, + ll198, ll199, ll200, ll201, ll202, ll203, ll204, ll205, ll206, ll207, + ll208, ll209, ll210, ll211, ll212, ll213, ll214, ll215, ll216, ll217, + ll218, ll219, ll220, ll221, ll222, ll223, ll224, ll225, ll226, ll227, + ll228, ll229, ll230, ll231, ll232, ll233, ll234, ll235, ll236, ll237, + ll238, ll239, ll240, ll241, ll242, ll243, ll244, ll245, ll246, ll247, + ll248, ll249, ll250, ll251, ll252, ll253, ll254, ll255, ll256, ll257, + ll258, ll259, ll260, ll261, ll262, ll263, ll264, ll265, ll266, ll267, + ll268, ll269, ll270, ll271, ll272, ll273, ll274, ll275, ll276, ll277, + ll278, ll279, ll280, ll281, ll282, ll283, ll284, ll285, ll286, ll287, + ll288, ll289, ll290, ll291, ll292, ll293, ll294, ll295, ll296, ll297, + ll298, ll299, ll300, ll301, ll302, ll303, ll304, ll305, ll306, ll307, + ll308, ll309, ll310, ll311, ll312, ll313, ll314, ll315, ll316, ll317, + ll318, ll319, ll320, ll321, ll322, ll323, ll324, ll325, ll326, ll327, + ll328, ll329, ll330, ll331, ll332, ll333, ll334, ll335, ll336, ll337, + ll338, ll339, ll340, ll341, ll342, ll343, ll344, ll345, ll346, ll347, + ll348, ll349, ll350, ll351, ll352, ll353, ll354, ll355, ll356, ll357, + ll358, ll359, ll360, ll361, ll362, ll363, ll364, ll365, ll366, ll367, + ll368, ll369, ll370, ll371, ll372, ll373, ll374, ll375, ll376, ll377, + ll378, ll379, ll380, ll381, ll382, ll383, ll384, ll385, ll386, ll387, + ll388, ll389, ll390, ll391, ll392, ll393, ll394, ll395, ll396, ll397, + ll398, ll399, ll400, ll401, ll402, ll403, ll404, ll405, ll406, ll407, + ll408, ll409, ll410, ll411, ll412, ll413, ll414, ll415, ll416, ll417, + ll418, ll419, ll420, ll421, ll422, ll423, ll424, ll425, ll426, ll427, + ll428, ll429, ll430, ll431, ll432, ll433, ll434, ll435, ll436, ll437, + ll438, ll439, ll440, ll441, ll442, ll443, ll444, ll445, ll446, ll447, + ll448, ll449, ll450, ll451, ll452, ll453, ll454, ll455, ll456, ll457, + ll458, ll459, ll460, ll461, ll462, ll463, ll464, ll465, ll466, ll467, + ll468, ll469, ll470, ll471, ll472, ll473, ll474, ll475, ll476, ll477, + ll478, ll479, ll480, ll481, ll482, ll483, ll484, ll485, ll486, ll487, + ll488, ll489, ll490, ll491, ll492, ll493, ll494, ll495, ll496, ll497, + ll498, ll499, ll500, ll501, ll502, ll503, ll504, ll505, ll506, ll507, + ll508, ll509, ll510, ll511; + + if (deopt) { + method_entered = true; + synchronized(monitor) { + do_monitor_acquire = true; + UnloadedClass1 res = new UnloadedClass1(); // forces deopt with c2 + res.field = 0; //forced deopt with c1 + return res; + } + } + return null; + } + + static boolean m2(boolean deopt) { + long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, + l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, + l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36, + l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48, + l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, + l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72, + l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84, + l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96, + l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107, + l108, l109, l110, l111, l112, l113, l114, l115, l116, l117, + l118, l119, l120, l121, l122, l123, l124, l125, l126, l127, + l128, l129, l130, l131, l132, l133, l134, l135, l136, l137, + l138, l139, l140, l141, l142, l143, l144, l145, l146, l147, + l148, l149, l150, l151, l152, l153, l154, l155, l156, l157, + l158, l159, l160, l161, l162, l163, l164, l165, l166, l167, + l168, l169, l170, l171, l172, l173, l174, l175, l176, l177, + l178, l179, l180, l181, l182, l183, l184, l185, l186, l187, + l188, l189, l190, l191, l192, l193, l194, l195, l196, l197, + l198, l199, l200, l201, l202, l203, l204, l205, l206, l207, + l208, l209, l210, l211, l212, l213, l214, l215, l216, l217, + l218, l219, l220, l221, l222, l223, l224, l225, l226, l227, + l228, l229, l230, l231, l232, l233, l234, l235, l236, l237, + l238, l239, l240, l241, l242, l243, l244, l245, l246, l247, + l248, l249, l250, l251, l252, l253, l254, l255, l256, l257, + l258, l259, l260, l261, l262, l263, l264, l265, l266, l267, + l268, l269, l270, l271, l272, l273, l274, l275, l276, l277, + l278, l279, l280, l281, l282, l283, l284, l285, l286, l287, + l288, l289, l290, l291, l292, l293, l294, l295, l296, l297, + l298, l299, l300, l301, l302, l303, l304, l305, l306, l307, + l308, l309, l310, l311, l312, l313, l314, l315, l316, l317, + l318, l319, l320, l321, l322, l323, l324, l325, l326, l327, + l328, l329, l330, l331, l332, l333, l334, l335, l336, l337, + l338, l339, l340, l341, l342, l343, l344, l345, l346, l347, + l348, l349, l350, l351, l352, l353, l354, l355, l356, l357, + l358, l359, l360, l361, l362, l363, l364, l365, l366, l367, + l368, l369, l370, l371, l372, l373, l374, l375, l376, l377, + l378, l379, l380, l381, l382, l383, l384, l385, l386, l387, + l388, l389, l390, l391, l392, l393, l394, l395, l396, l397, + l398, l399, l400, l401, l402, l403, l404, l405, l406, l407, + l408, l409, l410, l411, l412, l413, l414, l415, l416, l417, + l418, l419, l420, l421, l422, l423, l424, l425, l426, l427, + l428, l429, l430, l431, l432, l433, l434, l435, l436, l437, + l438, l439, l440, l441, l442, l443, l444, l445, l446, l447, + l448, l449, l450, l451, l452, l453, l454, l455, l456, l457, + l458, l459, l460, l461, l462, l463, l464, l465, l466, l467, + l468, l469, l470, l471, l472, l473, l474, l475, l476, l477, + l478, l479, l480, l481, l482, l483, l484, l485, l486, l487, + l488, l489, l490, l491, l492, l493, l494, l495, l496, l497, + l498, l499, l500, l501, l502, l503, l504, l505, l506, l507, + l508, l509, l510, l511; + + boolean do_m3 = false; + try { + do_m3 = m2(deopt); + } catch (StackOverflowError e) { + return true; + } + if (do_m3) { + try { + m1(deopt); + } catch (StackOverflowError e) {} + } + return false; + } + + // Used for synchronization betwen threads + static volatile boolean thread_started = false; + static volatile boolean do_monitor_acquire = false; + static volatile boolean monitor_acquired = false; + static volatile boolean method_entered = false; + + static Object monitor = new Object(); + + static public void main(String[] args) { + // get m1 compiled + for (int i = 0; i < 20000; i++) { + m1(false); + } + + Thread thread = new Thread() { + public void run() { + thread_started = true; + while(!do_monitor_acquire); + System.out.println("Ok to try to acquire the lock"); + synchronized(monitor) { + monitor_acquired = true; + } + } + }; + + thread.setDaemon(true); + thread.start(); + + while(!thread_started); + + m2(true); + + if (!method_entered) { + System.out.println("TEST PASSED"); + return; + } + + for (int i = 0; i < 10; i++) { + System.out.println("Is lock acquired?"); + if (monitor_acquired) { + System.out.println("TEST PASSED"); + return; + } + try { + Thread.sleep(10000); + } catch(InterruptedException ie) { + } + } + System.out.println("TEST FAILED"); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/6929067/Test6929067.sh --- a/hotspot/test/runtime/6929067/Test6929067.sh Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/runtime/6929067/Test6929067.sh Wed Apr 23 10:12:34 2014 +0200 @@ -18,115 +18,39 @@ ## Adding common setup Variables for running shell tests. . ${TESTSRC}/../../test_env.sh -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Linux) - gcc_cmd=`which gcc` - if [ "x$gcc_cmd" == "x" ]; then - echo "WARNING: gcc not found. Cannot execute test." 2>&1 - exit 0; - fi - NULL=/dev/null - PS=":" - FS="/" - ;; - * ) - echo "Test passed; only valid for Linux" - exit 0; - ;; -esac +if [ "${VM_OS}" != "linux" ] +then + echo "Test only valid for Linux" + exit 0 +fi -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion > vm_version.out 2>&1 - -# Bitness: -# Cannot simply look at TESTVMOPTS as -d64 is not -# passed if there is only a 64-bit JVM available. - -grep "64-Bit" vm_version.out > ${NULL} -if [ "$?" = "0" ] -then - COMP_FLAG="-m64" -else - COMP_FLAG="-m32" +gcc_cmd=`which gcc` +if [ "x$gcc_cmd" = "x" ]; then + echo "WARNING: gcc not found. Cannot execute test." 2>&1 + exit 0; fi +CFLAGS=-m${VM_BITS} -# Architecture: -# Translate uname output to JVM directory name, but permit testing -# 32-bit x86 on an x64 platform. -ARCH=`uname -m` -case "$ARCH" in - x86_64) - if [ "$COMP_FLAG" = "-m32" ]; then - ARCH=i386 - else - ARCH=amd64 - fi - ;; - ppc64) - if [ "$COMP_FLAG" = "-m32" ]; then - ARCH=ppc - else - ARCH=ppc64 - fi - ;; - sparc64) - if [ "$COMP_FLAG" = "-m32" ]; then - ARCH=sparc - else - ARCH=sparc64 - fi - ;; - arm*) - # 32-bit ARM machine: compiler may not recognise -m32 - COMP_FLAG="" - ARCH=arm - ;; - aarch64) - # 64-bit arm machine, could be testing 32 or 64-bit: - if [ "$COMP_FLAG" = "-m32" ]; then - ARCH=arm - else - ARCH=aarch64 - fi - ;; - i586) - ARCH=i386 - ;; - i686) - ARCH=i386 - ;; - # Assuming other ARCH values need no translation -esac - - -# VM type: need to know server or client -VMTYPE=client -grep Server vm_version.out > ${NULL} -if [ "$?" = "0" ] -then - VMTYPE=server -fi - - -LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE}:/usr/lib:$LD_LIBRARY_PATH +LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH -cp ${TESTSRC}${FS}*.java ${THIS_DIR} -${COMPILEJAVA}${FS}bin${FS}javac *.java +cp ${TESTSRC}/*.java ${THIS_DIR} +${COMPILEJAVA}/bin/javac *.java -echo "Architecture: ${ARCH}" -echo "Compilation flag: ${COMP_FLAG}" -echo "VM type: ${VMTYPE}" +echo "Architecture: ${VM_CPU}" +echo "Compilation flag: ${CFLAGS}" +echo "VM type: ${VM_TYPE}" +echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}" + # Note pthread may not be found thus invoke creation will fail to be created. # Check to ensure you have a /usr/lib/libpthread.so if you don't please look # for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. -$gcc_cmd -DLINUX ${COMP_FLAG} -o invoke \ - -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \ - -L${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE} \ - ${TESTSRC}${FS}invoke.c -ljvm -lpthread +$gcc_cmd -DLINUX ${CFLAGS} -o invoke \ + -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \ + -L${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ + ${TESTSRC}/invoke.c -ljvm -lpthread ./invoke exit $? diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/InitialThreadOverflow/invoke.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/InitialThreadOverflow/invoke.c Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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. + */ + +#include +#include + +#include + +JavaVM* jvm; + +void * +floobydust (void *p) { + JNIEnv *env; + jclass class_id; + jmethodID method_id; + + (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL); + + class_id = (*env)->FindClass (env, "DoOverflow"); + assert (class_id); + + method_id = (*env)->GetStaticMethodID(env, class_id, "printIt", "()V"); + assert (method_id); + + (*env)->CallStaticVoidMethod(env, class_id, method_id, NULL); + + (*jvm)->DetachCurrentThread(jvm); +} + +int +main (int argc, const char** argv) { + JavaVMOption options[1]; + options[0].optionString = (char*) "-Xss320k"; + + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + vm_args.options = options; + vm_args.nOptions = 1; + + JNIEnv* env; + jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); + assert(result >= 0); + + pthread_t thr; + pthread_create(&thr, NULL, floobydust, NULL); + pthread_join(thr, NULL); + + floobydust(NULL); + + return 0; +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/InitialThreadOverflow/invoke.cxx --- a/hotspot/test/runtime/InitialThreadOverflow/invoke.cxx Tue Apr 22 11:10:12 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - -#include -#include - -#include - -JavaVM* jvm; - -void * -floobydust (void *p) { - JNIEnv *env; - - jvm->AttachCurrentThread((void**)&env, NULL); - - jclass class_id = env->FindClass ("DoOverflow"); - assert (class_id); - - jmethodID method_id = env->GetStaticMethodID(class_id, "printIt", "()V"); - assert (method_id); - - env->CallStaticVoidMethod(class_id, method_id, NULL); - - jvm->DetachCurrentThread(); -} - -int -main (int argc, const char** argv) { - JavaVMOption options[1]; - options[0].optionString = (char*) "-Xss320k"; - - JavaVMInitArgs vm_args; - vm_args.version = JNI_VERSION_1_2; - vm_args.ignoreUnrecognized = JNI_TRUE; - vm_args.options = options; - vm_args.nOptions = 1; - - JNIEnv* env; - jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); - assert(result >= 0); - - pthread_t thr; - pthread_create(&thr, NULL, floobydust, NULL); - pthread_join(thr, NULL); - - floobydust(NULL); - - return 0; -} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/InitialThreadOverflow/testme.sh --- a/hotspot/test/runtime/InitialThreadOverflow/testme.sh Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/runtime/InitialThreadOverflow/testme.sh Wed Apr 23 10:12:34 2014 +0200 @@ -21,7 +21,6 @@ # or visit www.oracle.com if you need additional information or have any # questions. -# @ignore 8029139 # @test testme.sh # @bug 8009062 # @summary Poor performance of JNI AttachCurrentThread after fix for 7017193 @@ -44,31 +43,35 @@ exit 0 fi -gcc_cmd=`which g++` +gcc_cmd=`which gcc` if [ "x$gcc_cmd" = "x" ]; then - echo "WARNING: g++ not found. Cannot execute test." 2>&1 + echo "WARNING: gcc not found. Cannot execute test." 2>&1 exit 0; fi CFLAGS="-m${VM_BITS}" -LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH +LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH -cp ${TESTSRC}${FS}invoke.cxx . +cp ${TESTSRC}/invoke.c . # Copy the result of our @compile action: -cp ${TESTCLASSES}${FS}DoOverflow.class . +cp ${TESTCLASSES}/DoOverflow.class . -echo "Compilation flag: ${COMP_FLAG}" +echo "Architecture: ${VM_CPU}" +echo "Compilation flag: ${CFLAGS}" +echo "VM type: ${VM_TYPE}" +echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}" + # Note pthread may not be found thus invoke creation will fail to be created. # Check to ensure you have a /usr/lib/libpthread.so if you don't please look # for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. $gcc_cmd -DLINUX ${CFLAGS} -o invoke \ - -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \ - -L${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ - -ljvm -lpthread invoke.cxx + -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \ + -L${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ + -ljvm -lpthread invoke.c ./invoke exit $? diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/Thread/CancellableThreadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/Thread/CancellableThreadTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * This test is useful for finding out whether a Thread can have a + * private variable indicate whether or not it is finished, and to illustrate + * the ease with which Threads terminate each other. + * + * @test + */ + +public class CancellableThreadTest { + public static final int THREADPAIRS = Integer.parseInt(System.getProperty("test.threadpairs", "128")); + + public static void main(String args[]) { + Thread[] threads = new Thread[THREADPAIRS]; + Canceller[] cancellers = new Canceller[THREADPAIRS]; + + System.out.println("Running with " + THREADPAIRS + " thread pairs"); + + for (int i = 0; i < THREADPAIRS; i++) { + cancellers[i] = new Canceller(i); + threads[i] = new Thread(cancellers[i]); + threads[i].start(); + } + + for (int i = 0; i < THREADPAIRS; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) { + } + + if (cancellers[i].failed) { + throw new RuntimeException(" Test failed in " + i + " th pair. See error messages above."); + } + } + } +} + +class Canceller implements Runnable { + + private final CancellableTimer timer; + + public final String name; + public volatile boolean failed = false; + private volatile boolean hasBeenNotified = false; + + public Canceller(int index) { + this.name = "Canceller #" + index; + timer = new CancellableTimer(index, this); + } + + public void setHasBeenNotified() { + hasBeenNotified = true; + } + + /** + * This method contains the "action" of this Canceller Thread. + * It starts a CancellableTimer, waits, and then interrupts the + * CancellableTimer after the CancellableTimer notifies it. It then + * tries to join the CancellableTimer to itself and reports on whether + * it was successful in doing so. + */ + public void run() { + Thread timerThread = new Thread(timer); + + try { + synchronized(this) { + timerThread.start(); + wait(); + } + } catch (InterruptedException e) { + System.err.println(name + " was interrupted during wait()"); + failed = true; + } + + if (!hasBeenNotified) { + System.err.println(name + ".hasBeenNotified is not true as expected"); + failed = true; + } + + synchronized (timer) { + timerThread.interrupt(); + } + + try { + timerThread.join(); + } catch (InterruptedException ie) { + System.err.println(name + " was interrupted while joining " + + timer.name); + failed = true; + } + + if (timerThread.isAlive()) { + System.err.println(timer.name + " is still alive after " + name + + " attempted to join it."); + failed = true; + } + } +} + +/** + * This non-public class is the Thread which the Canceller Thread deliberately + * interrupts and then joins to itself after this Thread has slept for a few milliseconds. + */ + +class CancellableTimer implements Runnable { + + public final String name; + private final Canceller myCanceller; + + public CancellableTimer(int index, Canceller aCanceller) { + this.name = "CancellableTimer #" + index; + this.myCanceller = aCanceller; + } + + /** + * This is where this CancellableTimer does its work. It notifies its + * Canceller, waits for the Canceller to interrupt it, then catches the + * InterruptedException, and sleeps for a few milliseconds before exiting. + */ + public void run() { + try { + synchronized (this) { + synchronized (myCanceller) { + myCanceller.setHasBeenNotified(); + myCanceller.notify(); + } + wait(); + } + } catch (InterruptedException first) { + // isInterrupted should've been cleared here and we should not register a + // second interrupt + if (Thread.currentThread().isInterrupted()) { + System.err.println(name + " should not register an interrupt here"); + myCanceller.failed = true; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + System.err.println(name + " was interrupted when sleeping"); + myCanceller.failed = true; + } + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/runtime/verifier/TestMultiANewArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/verifier/TestMultiANewArray.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, 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. + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import static jdk.internal.org.objectweb.asm.Opcodes.*; +import com.oracle.java.testlibrary.*; + +/* + * @test TestMultiANewArray + * @bug 8038076 + * @library /testlibrary + * @compile -XDignore.symbol.file TestMultiANewArray.java + * @run main/othervm TestMultiANewArray 49 + * @run main/othervm TestMultiANewArray 50 + * @run main/othervm TestMultiANewArray 51 + * @run main/othervm TestMultiANewArray 52 + */ + +public class TestMultiANewArray { + public static void main(String... args) throws Exception { + int cfv = Integer.parseInt(args[0]); + writeClassFile(cfv); + System.err.println("Running with cfv: " + cfv); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("VerifyError"); + output.shouldHaveExitValue(1); + } + + public static void writeClassFile(int cfv) throws Exception { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(cfv, ACC_PUBLIC + ACC_SUPER, "ClassFile", null, "java/lang/Object", null); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); + mv.visitCode(); + mv.visitInsn(ICONST_1); + mv.visitInsn(ICONST_2); + mv.visitMultiANewArrayInsn("[I", 2); + mv.visitVarInsn(ASTORE, 1); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + + cw.visitEnd(); + + try (FileOutputStream fos = new FileOutputStream(new File("ClassFile.class"))) { + fos.write(cw.toByteArray()); + } + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Wed Apr 23 10:12:34 2014 +0200 @@ -30,13 +30,25 @@ private static final String osArch = System.getProperty("os.arch"); private static final String vmName = System.getProperty("java.vm.name"); - public static boolean isClient() { - return vmName.endsWith(" Client VM"); - } + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } - public static boolean isServer() { - return vmName.endsWith(" Server VM"); - } + public static boolean isGraal() { + return vmName.endsWith(" Graal VM"); + } + + public static boolean isMinimal() { + return vmName.endsWith(" Minimal VM"); + } + + public static boolean isEmbedded() { + return vmName.contains("Embedded"); + } public static boolean is32bit() { return dataModel.equals("32"); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Wed Apr 23 10:12:34 2014 +0200 @@ -145,18 +145,15 @@ return createJavaProcessBuilder(false, command); } - public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmOptions, String... command) throws Exception { + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception { String javapath = JDKToolFinder.getJDKTool("java"); ArrayList args = new ArrayList<>(); args.add(javapath); Collections.addAll(args, getPlatformSpecificVMArgs()); - if (addTestVmOptions) { - String vmopts = System.getProperty("test.vm.opts"); - if (vmopts != null && vmopts.length() > 0) { - Collections.addAll(args, vmopts.split("\\s")); - } + if (addTestVmAndJavaOptions) { + Collections.addAll(args, Utils.getTestJavaOpts()); } Collections.addAll(args, command); diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Wed Apr 23 10:12:34 2014 +0200 @@ -38,6 +38,8 @@ import java.util.Collections; import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.lang.reflect.Field; +import sun.misc.Unsafe; /** * Common library for various test helper functions. @@ -59,6 +61,8 @@ */ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + private static Unsafe unsafe = null; + /** * Returns the value of 'test.timeout.factor' system property * converted to {@code double}. @@ -109,10 +113,10 @@ /** * Returns the default JTReg arguments for a jvm running a test without - * options that matches regular expresions in {@code filters}. + * options that matches regular expressions in {@code filters}. * This is the combination of JTReg arguments test.vm.opts and test.java.opts. * @param filters Regular expressions used to filter out options. - * @return An array of options, or an empty array if no opptions. + * @return An array of options, or an empty array if no options. */ public static String[] getFilteredTestJavaOpts(String... filters) { String options[] = getTestJavaOpts(); @@ -294,4 +298,38 @@ return output; } + /** + * @return Unsafe instance. + */ + public static synchronized Unsafe getUnsafe() { + if (unsafe == null) { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + return unsafe; + } + private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /** + * Returns hex view of byte array + * + * @param bytes byte array to process + * @return Space separated hexadecimal string representation of bytes + */ + + public static String toHexString(byte[] bytes) { + char[] hexView = new char[bytes.length * 3]; + int i = 0; + for (byte b : bytes) { + hexView[i++] = hexArray[(b >> 4) & 0x0F]; + hexView[i++] = hexArray[b & 0x0F]; + hexView[i++] = ' '; + } + return new String(hexView); + } } diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -23,22 +23,16 @@ package com.oracle.java.testlibrary.cli; -import sun.hotspot.cpuinfo.CPUInfo; -import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.predicate.CPUSpecificPredicate; /** * Base class for command line options tests that * requires specific CPU arch or specific CPU features. */ public abstract class CPUSpecificCommandLineOptionTest - extends CommandLineOptionTest { - - private String cpuArchPattern; - private String supportedCPUFeatures[]; - private String unsupportedCPUFeatures[]; - + extends CommandLineOptionTest { /** - * Create new CPU specific test instance that does not + * Creates new CPU specific test instance that does not * require any CPU features. * * @param cpuArchPattern Regular expression that should @@ -49,62 +43,23 @@ } /** - * Create new CPU specific test instance that does not + * Creates new CPU specific test instance that does not * require from CPU support of {@code supportedCPUFeatures} features * and no support of {@code unsupportedCPUFeatures}. * * @param cpuArchPattern Regular expression that should * match os.arch. * @param supportedCPUFeatures Array with names of features that - * should be supported by CPU. If null, + * should be supported by CPU. If {@code null}, * then no features have to be supported. * @param unsupportedCPUFeatures Array with names of features that * should not be supported by CPU. - * If null, then CPU may support any + * If {@code null}, then CPU may support any * features. */ public CPUSpecificCommandLineOptionTest(String cpuArchPattern, - String supportedCPUFeatures[], - String unsupportedCPUFeatures[]) { - this.cpuArchPattern = cpuArchPattern; - this.supportedCPUFeatures = supportedCPUFeatures; - this.unsupportedCPUFeatures = unsupportedCPUFeatures; - } - - /** - * Check that CPU on test box has appropriate architecture, support all - * required features and does not support all features that should not be - * supported. - * - * @return true if CPU on test box fulfill all requirements. - */ - @Override - public boolean checkPreconditions() { - if (!Platform.getOsArch().matches(cpuArchPattern)) { - System.out.println("CPU arch does not match " + cpuArchPattern); - return false; - } - - if (supportedCPUFeatures != null) { - for (String feature : supportedCPUFeatures) { - if (!CPUInfo.hasFeature(feature)) { - System.out.println("CPU does not support " + feature + - " feature"); - return false; - } - } - } - - if (unsupportedCPUFeatures != null) { - for (String feature : unsupportedCPUFeatures) { - if (CPUInfo.hasFeature(feature)) { - System.out.println("CPU support " + feature + " feature"); - return false; - } - } - } - - return true; + String supportedCPUFeatures[], String unsupportedCPUFeatures[]) { + super(new CPUSpecificPredicate(cpuArchPattern, supportedCPUFeatures, + unsupportedCPUFeatures)); } } - diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Tue Apr 22 11:10:12 2014 +0200 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Wed Apr 23 10:12:34 2014 +0200 @@ -26,6 +26,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Collections; +import java.util.function.BooleanSupplier; import com.oracle.java.testlibrary.*; @@ -33,34 +34,71 @@ * Base class for command line option tests. */ public abstract class CommandLineOptionTest { - - public static final String UNRECOGNIZED_OPTION_ERROR_FORMAT = - "Unrecognized VM option '[+-]?%s'"; - - public static final String printFlagsFinalFormat = "%s\\s*:?=\\s*%s"; + public static final String UNLOCK_DIAGNOSTIC_VM_OPTIONS + = "-XX:+UnlockDiagnosticVMOptions"; + public static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS + = "-XX:+UnlockExperimentalVMOptions"; + protected static final String UNRECOGNIZED_OPTION_ERROR_FORMAT + = "Unrecognized VM option '[+-]?%s(=.*)?'"; + protected static final String EXPERIMENTAL_OPTION_ERROR_FORMAT + = "VM option '%s' is experimental and must be enabled via " + + "-XX:\\+UnlockExperimentalVMOptions."; + protected static final String DIAGNOSTIC_OPTION_ERROR_FORMAT + = " VM option '%s' is diagnostic and must be enabled via " + + "-XX:\\+UnlockDiagnosticVMOptions."; + private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s"; /** - * Verify that JVM startup behaviour matches our expectations. + * Verifies that JVM startup behaviour matches our expectations. * - * @param option The option that should be passed to JVM - * @param excpectedMessages Array of patterns that should occur - * in JVM output. If null then + * @param option an option that should be passed to JVM + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then * JVM output could be empty. - * @param unexpectedMessages Array of patterns that should not - * occur in JVM output. If null then - * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. * @param exitCode expected exit code. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyJVMStartup(String option, - String expectedMessages[], - String unexpectedMessages[], - ExitCode exitCode) - throws Throwable { + String expectedMessages[], String unexpectedMessages[], + ExitCode exitCode) throws Throwable { + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitCode, false, option); + } - OutputAnalyzer outputAnalyzer = - ProcessTools.executeTestJvm(option, "-version"); + /** + * Verifies that JVM startup behaviour matches our expectations. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitCode expected exit code. + * @param addTestVMOptions if {@code true} then test VM options will be + * passed to VM. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyJVMStartup(String expectedMessages[], + String unexpectedMessages[], ExitCode exitCode, + boolean addTestVMOptions, String... options) throws Throwable { + List finalOptions = new ArrayList<>(); + if (addTestVMOptions) { + Collections.addAll(finalOptions, Utils.getTestJavaOpts()); + } + Collections.addAll(finalOptions, options); + finalOptions.add("-version"); + ProcessBuilder processBuilder + = ProcessTools.createJavaProcessBuilder(finalOptions.toArray( + new String[finalOptions.size()])); + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); outputAnalyzer.shouldHaveExitValue(exitCode.value); if (expectedMessages != null) { @@ -77,97 +115,216 @@ } /** - * Verify that value of specified JVM option is the same as + * Verifies that JVM startup behaviour matches our expectations when type + * of newly started VM is the same as the type of current. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitCode expected exit code. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifySameJVMStartup(String expectedMessages[], + String unexpectedMessages[], ExitCode exitCode, String... options) + throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + Collections.addAll(finalOptions, options); + + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitCode, false, + finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Verifies that value of specified JVM option is the same as * expected value. * This method filter out option with {@code optionName} * name from test java options. * - * @param optionName Name of tested option. - * @param expectedValue Expected value of tested option. - * @param additionalVMOpts Additonal options that should be + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param additionalVMOpts additional options that should be * passed to JVM. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, - String... additionalVMOpts) - throws Throwable { + String expectedValue, String... additionalVMOpts) throws Throwable { verifyOptionValue(optionName, expectedValue, true, additionalVMOpts); } /** - * Verify that value of specified JVM option is the same as + * Verifies that value of specified JVM option is the same as * expected value. * This method filter out option with {@code optionName} * name from test java options. * - * @param optionName Name of tested option. - * @param expectedValue Expected value of tested option. - * @param addTestVmOptions If true, then test VM options + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param addTestVmOptions if {@code true}, then test VM options * will be used. - * @param additionalVMOpts Additonal options that should be + * @param additionalVMOpts additional options that should be * passed to JVM. - * @throws Throwable if verification fails or some other issues occur. + * @throws Throwable if verification fails or some other issues + * occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, - boolean addTestVmOptions, - String... additionalVMOpts) - throws Throwable { - - List vmOpts = new ArrayList(); + String expectedValue, boolean addTestVmOptions, + String... additionalVMOpts) throws Throwable { + List vmOpts = new ArrayList<>(); if (addTestVmOptions) { Collections.addAll(vmOpts, Utils.getFilteredTestJavaOpts(optionName)); } Collections.addAll(vmOpts, additionalVMOpts); - Collections.addAll(vmOpts, new String[] { - "-XX:+PrintFlagsFinal", - "-version" - }); + Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version"); - ProcessBuilder processBuilder = - ProcessTools. - createJavaProcessBuilder(vmOpts. - toArray(new String[vmOpts.size()])); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); - OutputAnalyzer outputAnalyzer = - new OutputAnalyzer(processBuilder.start()); + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); outputAnalyzer.shouldHaveExitValue(0); - outputAnalyzer.shouldMatch(String. - format(printFlagsFinalFormat, - optionName, - expectedValue)); + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionName, expectedValue)); + } + + /** + * Verifies that value of specified JVM when type of newly started VM + * is the same as the type of current. + * This method filter out option with {@code optionName} + * name from test java options. + * Only mode flag will be passed to VM in addition to + * {@code additionalVMOpts} + * + * @param optionName name of tested option. + * @param expectedValue expected value of tested option. + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValueForSameVM(String optionName, + String expectedValue, String... additionalVMOpts) throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + Collections.addAll(finalOptions, additionalVMOpts); + + CommandLineOptionTest.verifyOptionValue(optionName, expectedValue, + false, finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Prepares boolean command line flag with name {@code name} according + * to it's {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareBooleanFlag(String name, boolean value) { + return String.format("-XX:%c%s", (value ? '+' : '-'), name); + } + + /** + * Prepares numeric command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareNumericFlag(String name, Number value) { + return String.format("-XX:%s=%s", name, value.toString()); } + /** + * Returns message that should occur in VM output if option + * {@code optionName} if unrecognized. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is unrecognized + */ + public static String getUnrecognizedOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * Returns message that should occur in VM output if option + * {@code optionName} is experimental and + * -XX:+UnlockExperimentalVMOptions was not passed to VM. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is experimental + */ + public static String getExperimentalOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.EXPERIMENTAL_OPTION_ERROR_FORMAT, + optionName); + } /** - * Run command line option test. + * Returns message that should occur in VM output if option + * {@code optionName} is diagnostic and -XX:+UnlockDiagnosticVMOptions + * was not passed to VM. * - * @throws Throwable if test failed. + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is diganostic + */ + public static String getDiagnosticOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.DIAGNOSTIC_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * @return option required to start a new VM with the same type as current. + * @throws RuntimeException when VM type is unknown. + */ + private static String getVMTypeOption() { + if (Platform.isServer()) { + return "-server"; + } else if (Platform.isClient()) { + return "-client"; + } else if (Platform.isMinimal()) { + return "-minimal"; + } else if (Platform.isGraal()) { + return "-graal"; + } + throw new RuntimeException("Unknown VM mode."); + } + + private final BooleanSupplier predicate; + + /** + * Constructs new CommandLineOptionTest that will be executed only if + * predicate {@code predicate} return {@code true}. + * @param predicate a predicate responsible for test's preconditions check. + */ + public CommandLineOptionTest(BooleanSupplier predicate) { + this.predicate = predicate; + } + + /** + * Runs command line option test. */ public final void test() throws Throwable { - if (checkPreconditions()) { + if (predicate.getAsBoolean()) { runTestCases(); } } /** - * Check that all preconditions for test execution are met. - * - * @return true if test could be executed. + * @throws Throwable if some issue happened during test cases execution. */ - public boolean checkPreconditions() { - return true; - } - - /** - * Run test cases. - * - * @throws Throwable if test failed. - */ - public abstract void runTestCases() throws Throwable; + protected abstract void runTestCases() throws Throwable; } - diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class AndPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + + public AndPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() && b.getAsBoolean(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import com.oracle.java.testlibrary.Platform; +import sun.hotspot.cpuinfo.CPUInfo; + +import java.util.function.BooleanSupplier; + +public class CPUSpecificPredicate implements BooleanSupplier { + private final String cpuArchPattern; + private final String supportedCPUFeatures[]; + private final String unsupportedCPUFeatures[]; + + public CPUSpecificPredicate(String cpuArchPattern, + String supportedCPUFeatures[], + String unsupportedCPUFeatures[]) { + this.cpuArchPattern = cpuArchPattern; + this.supportedCPUFeatures = supportedCPUFeatures; + this.unsupportedCPUFeatures = unsupportedCPUFeatures; + } + + @Override + public boolean getAsBoolean() { + if (!Platform.getOsArch().matches(cpuArchPattern)) { + System.out.println("CPU arch does not match " + cpuArchPattern); + return false; + } + + if (supportedCPUFeatures != null) { + for (String feature : supportedCPUFeatures) { + if (!CPUInfo.hasFeature(feature)) { + System.out.println("CPU does not support " + feature + + " feature"); + return false; + } + } + } + + if (unsupportedCPUFeatures != null) { + for (String feature : unsupportedCPUFeatures) { + if (CPUInfo.hasFeature(feature)) { + System.out.println("CPU support " + feature + " feature"); + return false; + } + } + } + return true; + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class NotPredicate implements BooleanSupplier { + private final BooleanSupplier s; + + public NotPredicate(BooleanSupplier s) { + this.s = s; + } + + @Override + public boolean getAsBoolean() { + return !s.getAsBoolean(); + } +} diff -r dfc2242fc6b0 -r e378f2bfaaba hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java Wed Apr 23 10:12:34 2014 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class OrPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + + public OrPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() || b.getAsBoolean(); + } +}