--- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/ppc/vm/ppc.ad Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad Thu Apr 17 13:50:26 2014 -0400
@@ -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 &&
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
}
}
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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) {
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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); }
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
//
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
}
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
}
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
}
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Thu Apr 17 13:50:26 2014 -0400
@@ -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);
%}
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
}
//----------------------------------------------------------------------------------------------------
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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)
--- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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) {
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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.
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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()));
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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()));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Thu Apr 17 13:50:26 2014 -0400
@@ -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;
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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,
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<CallSite> 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;
+ }
}
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<CallSite> scopes = new Stack<CallSite>();
private Compilation compile;
private CallSite site;
+ private CallSite methodHandleSite;
private Stack<Phase> phaseStack = new Stack<Phase>();
private UncommonTrapEvent currentTrap;
- private Stack<CallSite> late_inline_scope;
+ private Stack<CallSite> 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<CallSite>();
+ long inlineId = Long.parseLong(search(atts, "inline_id"));
+ lateInlineScope = new Stack<CallSite>();
site = new CallSite(-999, method(search(atts, "method")));
- late_inline_scope.push(site);
+ site.setInlineId(inlineId);
+ lateInlineScope.push(site);
} else if (qname.equals("jvms")) {
// <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
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 <eliminate_allocation type='667'>,
// <eliminate_lock lock='1'>,
// <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
}
+ } 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<CallSite> thisCallScopes = new ArrayDeque<CallSite>();
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();
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Thu Apr 17 13:50:26 2014 -0400
@@ -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;
+ }
}
--- a/hotspot/src/share/vm/adlc/output_h.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/adlc/output_h.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
}
}
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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("<blob name='%s' size='%d'>", name, _total_size);
for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
+ }
};
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
};
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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());
}
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
--- a/hotspot/src/share/vm/ci/ciKlass.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciKlass.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ )
+}
--- a/hotspot/src/share/vm/ci/ciKlass.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciKlass.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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();
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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.
--- a/hotspot/src/share/vm/ci/ciSymbol.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciSymbol.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
//
--- a/hotspot/src/share/vm/ci/ciSymbol.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/ci/ciSymbol.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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.
--- a/hotspot/src/share/vm/compiler/compileLog.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/compiler/compileLog.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/compiler/compileLog.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/compiler/compileLog.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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,
--- a/hotspot/src/share/vm/opto/callGenerator.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
--- a/hotspot/src/share/vm/opto/callGenerator.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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.)
--- a/hotspot/src/share/vm/opto/callnode.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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; }
--- a/hotspot/src/share/vm/opto/callnode.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/callnode.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
--- a/hotspot/src/share/vm/opto/compile.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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");
--- a/hotspot/src/share/vm/opto/compile.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/compile.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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; }
--- a/hotspot/src/share/vm/opto/doCall.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/doCall.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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,
--- a/hotspot/src/share/vm/opto/escape.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/escape.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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");
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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-----------------------------
--- a/hotspot/src/share/vm/opto/loopnode.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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?
--- a/hotspot/src/share/vm/opto/loopopts.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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) {
--- a/hotspot/src/share/vm/opto/machnode.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/machnode.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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; }
--- a/hotspot/src/share/vm/opto/node.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/node.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
};
--- a/hotspot/src/share/vm/opto/output.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/output.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
}
--- a/hotspot/src/share/vm/opto/phaseX.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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--------------------------------------
--- a/hotspot/src/share/vm/opto/phaseX.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
}
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
}
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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();
}
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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) {
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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);
}
--- a/hotspot/src/share/vm/runtime/vframeArray.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/runtime/vframeArray.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -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;
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Thu Apr 17 13:50:26 2014 -0400
@@ -147,6 +147,9 @@
}
};
+template<class E> class GrowableArrayIterator;
+template<class E, class UnaryPredicate> class GrowableArrayFilterIterator;
+
template<class E> class GrowableArray : public GenericGrowableArray {
friend class VMStructs;
@@ -243,6 +246,14 @@
return _data[_len-1];
}
+ GrowableArrayIterator<E> begin() const {
+ return GrowableArrayIterator<E>(this, 0);
+ }
+
+ GrowableArrayIterator<E> end() const {
+ return GrowableArrayIterator<E>(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 E> class GrowableArrayIterator : public StackObj {
+ friend class GrowableArray<E>;
+ template<class F, class UnaryPredicate> friend class GrowableArrayFilterIterator;
+
+ private:
+ const GrowableArray<E>* _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<E>* array, int position) : _array(array), _position(position) {
+ assert(0 <= position && position <= _array->length(), "illegal position");
+ }
+
+ public:
+ GrowableArrayIterator<E>& operator++() { ++_position; return *this; }
+ E operator*() { return _array->at(_position); }
+
+ bool operator==(const GrowableArrayIterator<E>& rhs) {
+ assert(_array == rhs._array, "iterator belongs to different array");
+ return _position == rhs._position;
+ }
+
+ bool operator!=(const GrowableArrayIterator<E>& 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 E, class UnaryPredicate> class GrowableArrayFilterIterator : public StackObj {
+ friend class GrowableArray<E>;
+
+ private:
+ const GrowableArray<E>* _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<E>& 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<E, UnaryPredicate>& 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<E>& rhs) {
+ assert(_array == rhs._array, "iterator belongs to different array");
+ return _position == rhs._position;
+ }
+
+ bool operator!=(const GrowableArrayIterator<E>& rhs) {
+ assert(_array == rhs._array, "iterator belongs to different array");
+ return _position != rhs._position;
+ }
+
+ bool operator==(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
+ assert(_array == rhs._array, "iterator belongs to different array");
+ return _position == rhs._position;
+ }
+
+ bool operator!=(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
+ assert(_array == rhs._array, "iterator belongs to different array");
+ return _position != rhs._position;
+ }
+};
+
#endif // SHARE_VM_UTILITIES_GROWABLEARRAY_HPP
--- a/hotspot/src/share/vm/utilities/xmlstream.cpp Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/src/share/vm/utilities/xmlstream.cpp Thu Apr 17 13:50:26 2014 -0400
@@ -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
--- a/hotspot/test/TEST.groups Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/TEST.groups Thu Apr 17 13:50:26 2014 -0400
@@ -134,7 +134,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 = \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/EscapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java Thu Apr 17 13:50:26 2014 -0400
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<Method, BmiTestCase> 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<Integer> 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";
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Thu Apr 17 13:50:26 2014 -0400
@@ -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";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Thu Apr 17 13:50:26 2014 -0400
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<String> 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<String> 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()]));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java Thu Apr 17 13:50:26 2014 -0400
@@ -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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortThresholdOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMLockingThresholdOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMSpinLoopCountOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Thu Apr 17 13:50:26 2014 -0400
@@ -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:
+ * <pre>
+ *
+ * rtm state ^
+ * |
+ * UseRTM | ******| ******
+ * | |
+ * ProfileRTM |******| |*****|
+ * | | | |
+ * 0-------|-----|-----|---------------------> time
+ * | | \ force abort
+ * | |
+ * | \ force deoptimization
+ * |
+ * \ force xabort
+ * </pre>
+ * 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<RTMLockingStatistics> 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();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java Thu Apr 17 13:50:26 2014 -0400
@@ -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
+ * <i>rtm_state_change</i> 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<RTMLockingStatistics> 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();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Apr 17 13:50:26 2014 -0400
@@ -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
+ * <i>rtm_state_change</i> 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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <i>NoRTMLockElidingOption</i>
+ * will not use RTM-based lock elision.
+ * Test invokes compiled method and checks that no deoptimization with
+ * <i>rtm_state_change</i> 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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <i>UseRTMLockElidingOption</i>
+ * will use RTM-based lock elision, but will be never deoptimized with
+ * <i>rtm_state_change reason</i>.
+ * Test invokes compiled method and checks that no deoptimization with
+ * <i>rtm_state_change</i> 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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<String> 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<RTMLockingStatistics> 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<RTMLockingStatistics> 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java Thu Apr 17 13:50:26 2014 -0400
@@ -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:
+ * <ul>
+ * <li>inflate monitor = <b>true</b></li>
+ * <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
+ * <li>delay = <b>0</b></li>
+ * </ul>
+ */
+ 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";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/AbortType.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<Integer, AbortType> 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/BufferOverflowProvoker.java Thu Apr 17 13:50:26 2014 -0400
@@ -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]++;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Thu Apr 17 13:50:26 2014 -0400
@@ -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:
+ * <ul>
+ * <li>inflate monitor = {@code true}</li>
+ * <li>timeout = {@code BusyLock.DEFAULT_TIMEOUT}</li>
+ * </ul>
+ */
+ 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/CompilableTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Thu Apr 17 13:50:26 2014 -0400
@@ -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";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/NestedAbortProvoker.java Thu Apr 17 13:50:26 2014 -0400
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/RTMLockingStatistics.java Thu Apr 17 13:50:26 2014 -0400
@@ -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+(?<type>[0-9]+):\\s(?<count>[0-9]+)";
+
+ ABORT_PATTERN = Pattern.compile(abortRe);
+ RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile(
+ "(?<className>[^.\n]+)\\." +
+ "(?<methodName>[^@\n]+)@(?<bci>[0-9]+)\n" +
+ "# rtm locks total \\(estimated\\):\\s*" +
+ "(?<totalLocks>[0-9]+)\n" +
+ "# rtm lock aborts\\s+:\\s*(?<totalAborts>[0-9]+)\n" +
+ "(?<abortStats>(" + 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<AbortType, Long> 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<RTMLockingStatistics> fromString(String str) {
+ List<RTMLockingStatistics> 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<RTMLockingStatistics> fromString(String methodName,
+ String str) {
+ String formattedMethodName = formatMethodName(methodName);
+
+ List<RTMLockingStatistics> 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.
+ *
+ * <pre>
+ * 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
+ * </pre>
+ *
+ * @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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Apr 17 13:50:26 2014 -0400
@@ -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
+ = "<uncommon_trap thread='[0-9]+' reason='%s'";
+ private static final String INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE
+ = "<uncommon_trap bci='[0-9]+' reason='%s'";
+
+ /**
+ * Executes RTM test in a new JVM started with {@code options} cli options.
+ *
+ * @param test test case to execute.
+ * @param options additional options for VM
+ * @throws Exception when something went wrong.
+ */
+ public static OutputAnalyzer executeRTMTest(CompilableTest test,
+ String... options) throws Exception {
+ ProcessBuilder processBuilder
+ = ProcessTools.createJavaProcessBuilder(
+ RTMTestBase.prepareTestOptions(test, options));
+ OutputAnalyzer outputAnalyzer
+ = new OutputAnalyzer(processBuilder.start());
+ System.out.println(outputAnalyzer.getOutput());
+ return outputAnalyzer;
+ }
+
+ /**
+ * Executes test case and save compilation log to {@code logFileName}.
+ *
+ * @param logFileName a name of compilation log file
+ * @param test a test case to execute case to execute
+ * @param options additional options to VM
+ * @return OutputAnalyzer for started test case
+ * @throws Exception when something went wrong
+ */
+ public static OutputAnalyzer executeRTMTest(String logFileName,
+ CompilableTest test, String... options) throws Exception {
+ ProcessBuilder processBuilder
+ = ProcessTools.createJavaProcessBuilder(
+ RTMTestBase.prepareTestOptions(logFileName, test, options));
+ OutputAnalyzer outputAnalyzer
+ = new OutputAnalyzer(processBuilder.start());
+
+ System.out.println(outputAnalyzer.getOutput());
+
+ return outputAnalyzer;
+ }
+
+ /**
+ * Finds count of uncommon traps with reason {@code reason} installed
+ * during compilation.
+ *
+ * @param compilationLogFile a path to file with LogCompilation output.
+ * @param reason reason of installed uncommon traps.
+ * @return count of installed uncommon traps with reason {@code reason}.
+ * @throws IOException
+ */
+ public static int installedUncommonTraps(String compilationLogFile,
+ String reason)throws IOException {
+ String pattern = String.format(
+ RTMTestBase.INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE,
+ reason);
+ return RTMTestBase.findTraps(compilationLogFile, pattern);
+ }
+
+ /**
+ * Finds count of uncommon traps with reason <i>rtm_state_change</i>
+ * installed during compilation.
+ *
+ * @param compilationLogFile a path to file with LogCompilation output.
+ * @return count of installed uncommon traps with reason
+ * <i>rtm_state_change</i>.
+ * @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 <i>rtm_state_change</i>.
+ *
+ * @param compilationLogFile a path to file with LogCompilation output.
+ * @return count of fired uncommon traps with reason
+ * <i>rtm_state_change</i>.
+ * @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 <i>compileonly</i>
+ * 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 <i>compileonly</i>
+ * 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<String> 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<String> 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()]);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java Thu Apr 17 13:50:26 2014 -0400
@@ -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"
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java Thu Apr 17 13:50:26 2014 -0400
@@ -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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<Execution> 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<TypeHierarchy> 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<BiFunction<ProfilingType, TypeHierarchy, Scenario<?, ?>>> 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<ProfilingType, TypeHierarchy, Scenario<?, ?>> 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();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/OffTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/execution/Execution.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <T> parameter type
+ * @param <R> result Type
+ */
+public interface Execution<T extends TypeHierarchy.I, R> {
+ /**
+ * Executes the test code of the given scenario
+ * See {@link scenarios.Scenario#run(T)}
+ *
+ * @param scenario test scenario
+ */
+ void execute(Scenario<T, R> scenario);
+
+ default String getName() {
+ return this.getClass().getName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/execution/MethodHandleDelegate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I, R> implements Execution<T, R> {
+ private final Execution<T, R> delegate;
+
+ public MethodHandleDelegate(Execution<T, R> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void execute(Scenario<T, R> scenario) {
+ delegate.execute(new MHScenario<T, R>(scenario));
+ }
+
+ @Override
+ public String getName() {
+ return "MethodHandleDelegate # " + delegate.getName();
+ }
+
+ private static class MHScenario<T extends TypeHierarchy.I, R> extends Scenario<T, R> {
+ private final Scenario<T, R> 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<T, R> 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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/execution/TypeConflict.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I, R> implements Execution<T, R> {
+ /** 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<T, R> 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<T, R> scenario, T t) {
+ return scenario.run(t);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/execution/TypeProfile.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I, R> implements Execution<T, R> {
+ /** 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<T, R> 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<T, R> scenario, T t) {
+ return scenario.run(t);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<DefaultMethodInterface.A, DefaultMethodInterface.B> {
+ 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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/DefaultMethodInterface2.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<TypeHierarchy.A, DefaultMethodInterface2.B> {
+ 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()
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/Linear.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<TypeHierarchy.A, Linear.B> {
+ 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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/Linear2.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<TypeHierarchy.A, Linear2.B> {
+ 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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/NullableType.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<M extends TypeHierarchy.I, N extends TypeHierarchy.I>
+ extends TypeHierarchy<M, N> {
+
+ public NullableType(TypeHierarchy<M, N> delegate) {
+ super(delegate.getM(), null,
+ delegate.getClassM(), delegate.getClassN());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/OneRank.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<TypeHierarchy.A, OneRank.B> {
+ 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;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/hierarchies/TypeHierarchy.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<M extends TypeHierarchy.I, N extends TypeHierarchy.I> {
+ // 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<M> classM;
+ private final Class<N> classN;
+
+ protected TypeHierarchy(M m, N n, Class<M> classM, Class<N> 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<M> getClassM() {
+ return classM;
+ }
+
+ public final Class<N> getClassN() {
+ return classN;
+ }
+
+ public interface I {
+ int m();
+ }
+
+ public static class A implements I {
+ @Override
+ public int m() {
+ return TypeHierarchy.ANSWER;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayCopy.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<? extends TypeHierarchy.I, ? extends TypeHierarchy.I> 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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayReferenceStore.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<? extends TypeHierarchy.I, ? extends TypeHierarchy.I> 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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ArrayScenario.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<TypeHierarchy.I, TypeHierarchy.I> {
+ protected final TypeHierarchy.I[] array;
+ protected final TypeHierarchy.I[][] matrix;
+
+ protected ArrayScenario(String name, ProfilingType profilingType,
+ TypeHierarchy<? extends TypeHierarchy.I, ? extends TypeHierarchy.I> 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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/CheckCast.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <T> profiling parameter
+ */
+public class CheckCast<T extends TypeHierarchy.I> extends Scenario<T, Integer> {
+ public CheckCast(ProfilingType profilingType, TypeHierarchy<? extends T, ? extends T> 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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ClassIdentity.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I> extends Scenario<T, Integer> {
+ public ClassIdentity(ProfilingType profilingType,
+ TypeHierarchy<? extends T, ? extends T> 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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ClassInstanceOf.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I> extends Scenario<T, Integer> {
+ public ClassInstanceOf(ProfilingType profilingType,
+ TypeHierarchy<? extends T, ? extends T> 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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ClassIsInstance.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<T extends TypeHierarchy.I> extends Scenario<T, Integer> {
+ private final Class<?> baseClass;
+
+ public ClassIsInstance(ProfilingType profilingType,
+ TypeHierarchy<? extends T, ? extends T> 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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ProfilingType.java Thu Apr 17 13:50:26 2014 -0400
@@ -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,
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/ReceiverAtInvokes.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <T> parameter to be returned
+ */
+public class ReceiverAtInvokes<T extends TypeHierarchy.I> extends Scenario<T, Integer> {
+ public ReceiverAtInvokes(ProfilingType profilingType,
+ TypeHierarchy<? extends T, ? extends T> 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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/correctness/scenarios/Scenario.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <T> parameter type
+ * @param <R> result type
+ */
+public abstract class Scenario<T extends TypeHierarchy.I, R> {
+
+ private final String name;
+ public final ProfilingType profilingType;
+ public final TypeHierarchy <? extends T, ? extends T> 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<? extends T, ? extends T> 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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Thu Apr 17 13:50:26 2014 -0400
@@ -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");
+ }
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Apr 17 13:50:26 2014 -0400
@@ -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");
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Thu Apr 17 13:50:26 2014 -0400
@@ -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<String> 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);
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Apr 17 13:50:26 2014 -0400
@@ -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);
+ }
}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <b>null</b>,
+ * 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 <b>null</b>, 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 <b>true</b> 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));
}
}
-
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Tue Apr 15 19:03:51 2014 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Thu Apr 17 13:50:26 2014 -0400
@@ -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 <b>null</b> 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 <b>null</b> 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<String> 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<String> 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 <b>true</b>, 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<String> vmOpts = new ArrayList<String>();
+ String expectedValue, boolean addTestVmOptions,
+ String... additionalVMOpts) throws Throwable {
+ List<String> 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<String> 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 <b>true</b> 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;
}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java Thu Apr 17 13:50:26 2014 -0400
@@ -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();
+ }
+}