8032410: compiler/uncommontrap/TestStackBangRbp.java times out on Solaris-Sparc V9

Make compiled code bang the stack by the worst case size of the interpreter frame at deoptimization points.

Reviewed-by: twisti, kvn
This commit is contained in:
Roland Westrelin 2014-04-01 09:36:49 +02:00
parent bce45e9222
commit f5adc57f94
44 changed files with 1209 additions and 760 deletions

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved. * Copyright 2012, 2014 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2947,17 +2947,60 @@ void BytecodeInterpreter::pd_layout_interpreterState(interpreterState istate,
istate->_last_Java_fp = last_Java_fp; istate->_last_Java_fp = last_Java_fp;
} }
int AbstractInterpreter::layout_activation(Method* method, // Computes monitor_size and top_frame_size in bytes.
int temps, // Number of slots on java expression stack in use. static void frame_size_helper(int max_stack,
int popframe_args, int monitors,
int monitors, // Number of active monitors. int& monitor_size,
int caller_actual_parameters, int& top_frame_size) {
int callee_params,// Number of slots for callee parameters. monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors;
int callee_locals,// Number of slots for locals. top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes()
frame* caller, + monitor_size
frame* interpreter_frame, + max_stack * Interpreter::stackElementSize
bool is_top_frame, + 2 * Interpreter::stackElementSize,
bool is_bottom_frame) { 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 // NOTE this code must exactly mimic what
// InterpreterGenerator::generate_compute_interpreter_state() does // InterpreterGenerator::generate_compute_interpreter_state() does
@ -2967,86 +3010,64 @@ int AbstractInterpreter::layout_activation(Method* method,
// both the abi scratch area and a place to hold a result from a // both the abi scratch area and a place to hold a result from a
// callee on its way to the callers stack. // callee on its way to the callers stack.
int monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors; int monitor_size = 0;
int frame_size; int top_frame_size = 0;
int top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() frame_size_helper(method->max_stack(), monitors, monitor_size, top_frame_size);
+ 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;
} 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");
}
// If we actually have a frame to layout we must now fill in all the pieces. intptr_t sp = (intptr_t)interpreter_frame->sp();
if (interpreter_frame != NULL) { 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());
intptr_t sp = (intptr_t)interpreter_frame->sp(); // Now fill in the interpreterState object.
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()) {
intptr_t* locals; // Locals must agree with the caller because it will be used to set the
if (caller->is_interpreted_frame()) { // caller's tos when we return.
// Locals must agree with the caller because it will be used to set the interpreterState prev = caller->get_interpreterState();
// caller's tos when we return. // Calculate start of "locals" for MH calls. For MH calls, the
interpreterState prev = caller->get_interpreterState(); // current method() (= MH target) and prev->callee() (=
// Calculate start of "locals" for MH calls. For MH calls, the // MH.invoke*()) are different and especially have different
// current method() (= MH target) and prev->callee() (= // signatures. To pop the argumentsof the caller, we must use
// MH.invoke*()) are different and especially have different // the prev->callee()->size_of_arguments() because that's what
// signatures. To pop the argumentsof the caller, we must use // the caller actually pushed. Currently, for synthetic MH
// the prev->callee()->size_of_arguments() because that's what // calls (deoptimized from inlined MH calls), detected by
// the caller actually pushed. Currently, for synthetic MH // is_method_handle_invoke(), we use the callee's arguments
// calls (deoptimized from inlined MH calls), detected by // because here, the caller's and callee's signature match.
// is_method_handle_invoke(), we use the callee's arguments if (true /*!caller->is_at_mh_callsite()*/) {
// because here, the caller's and callee's signature match. locals = prev->stack() + method->size_of_parameters();
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 { } else {
bool is_deopted; // Normal MH call.
locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) + locals = prev->stack() + prev->callee()->size_of_parameters();
frame::parent_ijava_frame_abi_size);
} }
} else {
intptr_t* monitor_base = (intptr_t*) cur_state; bool is_deopted;
intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) +
frame::parent_ijava_frame_abi_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 #endif // CC_INTERP

View File

@ -1,6 +1,6 @@
// //
// Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
// Copyright 2012, 2013 SAP AG. All rights reserved. // Copyright 2012, 2014 SAP AG. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// //
// This code is free software; you can redistribute it and/or modify it // This code is free software; you can redistribute it and/or modify it
@ -1362,8 +1362,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
const long framesize = ((long)C->frame_slots()) << LogBytesPerInt; const long framesize = C->frame_size_in_bytes();
assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); assert(framesize % (2 * wordSize) == 0, "must preserve 2*wordSize alignment");
const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/;
@ -1388,19 +1388,22 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// careful, because some VM calls (such as call site linkage) can // careful, because some VM calls (such as call site linkage) can
// use several kilobytes of stack. But the stack safety zone should // use several kilobytes of stack. But the stack safety zone should
// account for that. See bugs 4446381, 4468289, 4497237. // 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 // Unfortunately we cannot use the function provided in
// assembler.cpp as we have to emulate the pipes. So I had to // assembler.cpp as we have to emulate the pipes. So I had to
// insert the code of generate_stack_overflow_check(), see // insert the code of generate_stack_overflow_check(), see
// assembler.cpp for some illuminative comments. // assembler.cpp for some illuminative comments.
const int page_size = os::vm_page_size(); 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. // This is how far the previous frame's stack banging extended.
const int bang_end_safe = bang_end; const int bang_end_safe = bang_end;
if (framesize > page_size) { if (bangsize > page_size) {
bang_end += framesize; bang_end += bangsize;
} }
int bang_offset = bang_end_safe; int bang_offset = bang_end_safe;
@ -1446,7 +1449,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
unsigned int bytes = (unsigned int)framesize; unsigned int bytes = (unsigned int)framesize;
long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes); long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes);
ciMethod *currMethod = C -> method(); ciMethod *currMethod = C->method();
// Optimized version for most common case. // Optimized version for most common case.
if (UsePower6SchedulerPPC64 && if (UsePower6SchedulerPPC64 &&

View File

@ -1334,21 +1334,42 @@ bool AbstractInterpreter::can_be_compiled(methodHandle m) {
int AbstractInterpreter::size_top_interpreter_activation(Method* method) { int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
const int max_alignment_size = 2; const int max_alignment_size = 2;
const int abi_scratch = frame::abi_reg_args_size; 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 // Returns number of stackElementWords needed for the interpreter frame with the
// and returns the frame size in slots. // 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: // 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: // interpreter_frame != NULL:
// set up the method, locals, and monitors. // set up the method, locals, and monitors.
// The frame interpreter_frame, if not NULL, is guaranteed to be the // The frame interpreter_frame, if not NULL, is guaranteed to be the
@ -1365,59 +1386,41 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
// the arguments off advance the esp by dummy popframe_extra_args slots. // 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. // Popping off those will establish the stack layout as it was before the call.
// //
int AbstractInterpreter::layout_activation(Method* method, void AbstractInterpreter::layout_activation(Method* method,
int tempcount, int tempcount,
int popframe_extra_args, int popframe_extra_args,
int moncount, int moncount,
int caller_actual_parameters, int caller_actual_parameters,
int callee_param_count, int callee_param_count,
int callee_locals, int callee_locals_count,
frame* caller, frame* caller,
frame* interpreter_frame, frame* interpreter_frame,
bool is_top_frame, bool is_top_frame,
bool is_bottom_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) : const int abi_scratch = is_top_frame ? (frame::abi_reg_args_size / Interpreter::stackElementSize) :
(frame::abi_minframe_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"); 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) ;
if (interpreter_frame == NULL) { intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize ;
// Since we don't know the exact alignment, we return the conservative size. intptr_t* monitor = monitor_base - (moncount * frame::interpreter_frame_monitor_size());
return (conservative_framesize_in_slots & -2); intptr_t* esp_base = monitor - 1;
} else { intptr_t* esp = esp_base - tempcount - popframe_extra_args;
// Now we know our caller, calc the exact frame layout and size. intptr_t* sp = (intptr_t *) (((intptr_t) (esp_base - callee_locals_count + callee_param_count - method->max_stack()- abi_scratch)) & -StackAlignmentInBytes);
intptr_t* locals_base = (caller->is_interpreted_frame()) ? intptr_t* sender_sp = caller->sp() + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize;
caller->interpreter_frame_esp() + caller_actual_parameters : intptr_t* top_frame_sp = is_top_frame ? sp : sp + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize;
caller->sp() + method->max_locals() - 1 + (frame::abi_minframe_size / Interpreter::stackElementSize) ;
intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize ; interpreter_frame->interpreter_frame_set_method(method);
intptr_t* monitor = monitor_base - (moncount * frame::interpreter_frame_monitor_size()); interpreter_frame->interpreter_frame_set_locals(locals_base);
intptr_t* esp_base = monitor - 1; interpreter_frame->interpreter_frame_set_cpcache(method->constants()->cache());
intptr_t* esp = esp_base - tempcount - popframe_extra_args; interpreter_frame->interpreter_frame_set_esp(esp);
intptr_t* sp = (intptr_t *) (((intptr_t) (esp_base- callee_locals + callee_param_count - method->max_stack()- abi_scratch)) & -StackAlignmentInBytes); interpreter_frame->interpreter_frame_set_monitor_end((BasicObjectLock *)monitor);
intptr_t* sender_sp = caller->sp() + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; interpreter_frame->interpreter_frame_set_top_frame_sp(top_frame_sp);
intptr_t* top_frame_sp = is_top_frame ? sp : sp + (frame::abi_minframe_size - frame::abi_reg_args_size) / Interpreter::stackElementSize; if (!is_bottom_frame) {
interpreter_frame->interpreter_frame_set_sender_sp(sender_sp);
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;
} }
} }

View File

@ -152,7 +152,7 @@ LIR_Opr LIR_Assembler::osrBufferPointer() {
} }
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()); return in_bytes(frame_map()->framesize_in_bytes());
} }
@ -182,7 +182,7 @@ void LIR_Assembler::osr_entry() {
int number_of_locks = entry_state->locks_size(); int number_of_locks = entry_state->locks_size();
// Create a frame for the compiled activation. // 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 // OSR buffer is
// //

View File

@ -55,9 +55,9 @@ void C1_MacroAssembler::explicit_null_check(Register base) {
} }
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");
generate_stack_overflow_check(frame_size_in_bytes); generate_stack_overflow_check(bang_size_in_bytes);
// Create the frame. // Create the frame.
save_frame_c1(frame_size_in_bytes); save_frame_c1(frame_size_in_bytes);
} }

View File

@ -2099,7 +2099,7 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
int monitor_size = method->is_synchronized() ? int monitor_size = method->is_synchronized() ?
1*frame::interpreter_frame_monitor_size() : 0; 1*frame::interpreter_frame_monitor_size() : 0;
return size_activation_helper(method->max_locals(), method->max_stack(), 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, void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
@ -2183,31 +2183,31 @@ void BytecodeInterpreter::pd_layout_interpreterState(interpreterState istate, ad
istate->_last_Java_pc = (intptr_t*) last_Java_pc; istate->_last_Java_pc = (intptr_t*) last_Java_pc;
} }
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;
int AbstractInterpreter::layout_activation(Method* method, return frame_words;
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"); int AbstractInterpreter::size_activation(int max_stack,
// NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() int tempcount,
// does as far as allocating an interpreter frame. int extra_args,
// If interpreter_frame!=NULL, set up the method, locals, and monitors. int moncount,
// The frame interpreter_frame, if not NULL, is guaranteed to be the right size, int callee_param_size,
// as determined by a previous call to this method. int callee_locals_size,
// It is also guaranteed to be walkable even though it is in a skeletal state bool is_top_frame) {
assert(extra_args == 0, "NEED TO FIX");
// NOTE: return size is in words not bytes // 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 // Calculate the amount our frame will be adjust by the callee. For top frame
// this is zero. // this is zero.
@ -2216,87 +2216,108 @@ int AbstractInterpreter::layout_activation(Method* method,
// to it. So it ignores last_frame_adjust value. Seems suspicious as far // to it. So it ignores last_frame_adjust value. Seems suspicious as far
// as getting sender_sp correct. // as getting sender_sp correct.
int extra_locals_size = callee_locals_size - callee_param_size; int unused_monitor_size = 0;
int monitor_size = (sizeof(BasicObjectLock) * moncount) / wordSize; int unused_full_frame_words = 0;
int full_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size); return frame_size_helper(max_stack, moncount, callee_param_size, callee_locals_size, is_top_frame,
int short_frame_words = size_activation_helper(extra_locals_size, method->max_stack(), monitor_size); unused_monitor_size, unused_full_frame_words);
int frame_words = is_top_frame ? full_frame_words : short_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. 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); 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. // '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"); assert(((intptr_t)frame_bottom & 0xf) == 0, "SP biased in layout_activation");
frame_bottom = (intptr_t*)((intptr_t)frame_bottom - STACK_BIAS); 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 // Calculate the postion of locals[0]. This is painful because of
// stack alignment (same as ia64). The problem is that we can // stack alignment (same as ia64). The problem is that we can
// not compute the location of locals from fp(). fp() will account // not compute the location of locals from fp(). fp() will account
// for the extra locals but it also accounts for aligning the stack // 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 // and we can't determine if the locals[0] was misaligned but max_locals
// was enough to have the // was enough to have the
// calculate postion of locals. fp already accounts for extra locals. // calculate postion of locals. fp already accounts for extra locals.
// +2 for the static long no_params() issue. // +2 for the static long no_params() issue.
if (caller->is_interpreted_frame()) { if (caller->is_interpreted_frame()) {
// locals must agree with the caller because it will be used to set the // locals must agree with the caller because it will be used to set the
// caller's tos when we return. // caller's tos when we return.
interpreterState prev = caller->get_interpreterState(); interpreterState prev = caller->get_interpreterState();
// stack() is prepushed. // stack() is prepushed.
locals = prev->stack() + method->size_of_parameters(); 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_compiled_frame()) {
locals = fp + frame::register_save_words + local_words - 1;
} else { } else {
// Lay out locals block in the caller adjacent to the register window save area. locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1;
//
// 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_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
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::pd_layout_interpreterState(cur_state, interpreter_return_address, interpreter_frame->fp());
} }
return frame_words; // 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);
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());
} }
#endif // CC_INTERP #endif // CC_INTERP

View File

@ -3531,7 +3531,7 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp,
// was post-decremented.) Skip this address by starting at i=1, and // 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 // touch a few more pages below. N.B. It is important to touch all
// the way down to and including i=StackShadowPages. // 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); set((-i*offset)+STACK_BIAS, Rscratch);
st(G0, Rtsp, Rscratch); st(G0, Rtsp, Rscratch);
} }

View File

@ -3355,13 +3355,16 @@ static void make_new_frames(MacroAssembler* masm, bool deopt) {
Register O4array_size = O4; Register O4array_size = O4;
Label loop; Label loop;
// Before we make new frames, check to see if stack is available. #ifdef ASSERT
// Do this after the caller's return address is on top of stack // 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) { if (UseStackBanging) {
// Get total frame size for interpreted frames // Get total frame size for interpreted frames
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes(), O4); __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes(), O4);
__ bang_stack_size(O4, O3, G3_scratch); __ bang_stack_size(O4, O3, G3_scratch);
} }
#endif
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), O4array_size); __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), O4array_size);
__ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), G3pcs); __ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), G3pcs);
@ -3409,9 +3412,11 @@ void SharedRuntime::generate_deopt_blob() {
ResourceMark rm; ResourceMark rm;
// setup code generation tools // setup code generation tools
int pad = VerifyThread ? 512 : 0;// Extra slop space for more verify code int pad = VerifyThread ? 512 : 0;// Extra slop space for more verify code
#ifdef ASSERT
if (UseStackBanging) { if (UseStackBanging) {
pad += StackShadowPages*16 + 32; pad += StackShadowPages*16 + 32;
} }
#endif
#ifdef _LP64 #ifdef _LP64
CodeBuffer buffer("deopt_blob", 2100+pad, 512); CodeBuffer buffer("deopt_blob", 2100+pad, 512);
#else #else
@ -3632,9 +3637,11 @@ void SharedRuntime::generate_uncommon_trap_blob() {
ResourceMark rm; ResourceMark rm;
// setup code generation tools // setup code generation tools
int pad = VerifyThread ? 512 : 0; int pad = VerifyThread ? 512 : 0;
#ifdef ASSERT
if (UseStackBanging) { if (UseStackBanging) {
pad += StackShadowPages*16 + 32; pad += StackShadowPages*16 + 32;
} }
#endif
#ifdef _LP64 #ifdef _LP64
CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512); CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512);
#else #else

View File

@ -1193,15 +1193,16 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("Verify_Thread"); st->print("\t"); 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. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be careful, because // 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 // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(framesize)) { if (C->need_stack_bang(bangsize)) {
st->print_cr("! stack bang"); st->print("\t"); st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
} }
if (Assembler::is_simm13(-framesize)) { if (Assembler::is_simm13(-framesize)) {
@ -1225,17 +1226,18 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ verify_thread(); __ 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 >= 16*wordSize, "must have room for reg. save area");
assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); 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. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be careful, because // 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 // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(framesize)) { if (C->need_stack_bang(bangsize)) {
__ generate_stack_overflow_check(framesize); __ generate_stack_overflow_check(bangsize);
} }
if (Assembler::is_simm13(-framesize)) { if (Assembler::is_simm13(-framesize)) {
@ -2547,7 +2549,7 @@ encode %{
enc_class call_epilog %{ enc_class call_epilog %{
if( VerifyStackAtCalls ) { if( VerifyStackAtCalls ) {
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = ra_->C->frame_slots() << LogBytesPerInt; int framesize = ra_->C->frame_size_in_bytes();
Register temp_reg = G3; Register temp_reg = G3;
__ add(SP, framesize, temp_reg); __ add(SP, framesize, temp_reg);
__ cmp(temp_reg, FP); __ cmp(temp_reg, FP);

View File

@ -1564,37 +1564,23 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
int monitor_size = method->is_synchronized() ? int monitor_size = method->is_synchronized() ?
1*frame::interpreter_frame_monitor_size() : 0; 1*frame::interpreter_frame_monitor_size() : 0;
return size_activation_helper(method->max_locals(), method->max_stack(), 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 AbstractInterpreter::size_activation(int max_stack,
int tempcount, int temps,
int popframe_extra_args, int extra_args,
int moncount, int monitors,
int caller_actual_parameters, int callee_params,
int callee_param_count, int callee_locals,
int callee_local_count, bool is_top_frame) {
frame* caller,
frame* interpreter_frame,
bool is_top_frame,
bool is_bottom_frame) {
// Note: This calculation must exactly parallel the frame setup // Note: This calculation must exactly parallel the frame setup
// in InterpreterGenerator::generate_fixed_frame. // 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 monitor_size = monitors * frame::interpreter_frame_monitor_size();
int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong);
assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align");
// //
// Note: if you look closely this appears to be doing something much different // 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 // than generate_fixed_frame. What is happening is this. On sparc we have to do
@ -1619,146 +1605,171 @@ int AbstractInterpreter::layout_activation(Method* method,
// there is no sense in messing working code. // 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"); assert(rounded_cls == round_to(rounded_cls, WordsPerLong), "must align");
int raw_frame_size = size_activation_helper(rounded_cls, method->max_stack(), int raw_frame_size = size_activation_helper(rounded_cls, max_stack, monitor_size);
monitor_size);
if (interpreter_frame != NULL) { return raw_frame_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");
intptr_t* fp = interpreter_frame->fp(); 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.
JavaThread* thread = JavaThread::current(); // The skeleton frame must already look like an interpreter frame
RegisterMap map(thread, false); // even if not fully filled out.
// More verification that skeleton frame is properly walkable assert(interpreter_frame->is_interpreted_frame(), "Must be interpreted frame");
assert(fp == caller->sp(), "fp must match");
intptr_t* montop = fp - rounded_vm_local_words; 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");
// preallocate monitors (cf. __ add_monitor_to_stack) intptr_t* fp = interpreter_frame->fp();
intptr_t* monitors = montop - monitor_size;
// preallocate stack space JavaThread* thread = JavaThread::current();
intptr_t* esp = monitors - 1 - RegisterMap map(thread, false);
(tempcount * Interpreter::stackElementWords) - // More verification that skeleton frame is properly walkable
popframe_extra_args; assert(fp == caller->sp(), "fp must match");
int local_words = method->max_locals() * Interpreter::stackElementWords; intptr_t* montop = fp - rounded_vm_local_words;
NEEDS_CLEANUP;
intptr_t* locals; // preallocate monitors (cf. __ add_monitor_to_stack)
if (caller->is_interpreted_frame()) { intptr_t* monitors = montop - monitor_size;
// 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; // preallocate stack space
// Note that this computation means we replace size_of_parameters() values from the caller intptr_t* esp = monitors - 1 -
// interpreter frame's expression stack with our argument locals (tempcount * Interpreter::stackElementWords) -
int parm_words = caller_actual_parameters * Interpreter::stackElementWords; popframe_extra_args;
locals = Lesp_ptr + parm_words;
int delta = local_words - parm_words; int local_words = method->max_locals() * Interpreter::stackElementWords;
int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0; NEEDS_CLEANUP;
*interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS; intptr_t* locals;
if (!is_bottom_frame) { if (caller->is_interpreted_frame()) {
// Llast_SP is set below for the current frame to SP (with the // Can force the locals area to end up properly overlapping the top of the expression stack.
// extra space for the callee's locals). Here we adjust intptr_t* Lesp_ptr = caller->interpreter_frame_tos_address() - 1;
// Llast_SP for the caller's frame, removing the extra space // Note that this computation means we replace size_of_parameters() values from the caller
// for the current method's locals. // interpreter frame's expression stack with our argument locals
*caller->register_addr(Llast_SP) = *interpreter_frame->register_addr(I5_savedSP); int parm_words = caller_actual_parameters * Interpreter::stackElementWords;
} else { locals = Lesp_ptr + parm_words;
assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP"); 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 { } else {
assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases"); assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP");
// Don't have Lesp available; lay out locals block in the caller }
// adjacent to the register window save area. } else {
// assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases");
// Compiled frames do not allocate a varargs area which is why this if // Don't have Lesp available; lay out locals block in the caller
// statement is needed. // adjacent to the register window save area.
// //
if (caller->is_compiled_frame()) { // Compiled frames do not allocate a varargs area which is why this if
locals = fp + frame::register_save_words + local_words - 1; // statement is needed.
} else { //
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;
if (!caller->is_entry_frame()) { } else {
// Caller wants his own SP back locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1;
int caller_frame_size = caller->cb()->frame_size(); }
*interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS; 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_interpreted_frame()) {
if (caller->is_entry_frame()) { tty->print("interpreted ");
// 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);
} }
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) { if (method->max_locals() > 0) {
assert(locals < caller->sp() || locals >= (caller->sp() + 16), "locals in save area"); 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 < 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->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area");
assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area");
} }
#ifdef _LP64 #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 #endif
*interpreter_frame->register_addr(Lmethod) = (intptr_t) method; *interpreter_frame->register_addr(Lmethod) = (intptr_t) method;
*interpreter_frame->register_addr(Llocals) = (intptr_t) locals; *interpreter_frame->register_addr(Llocals) = (intptr_t) locals;
*interpreter_frame->register_addr(Lmonitors) = (intptr_t) monitors; *interpreter_frame->register_addr(Lmonitors) = (intptr_t) monitors;
*interpreter_frame->register_addr(Lesp) = (intptr_t) esp; *interpreter_frame->register_addr(Lesp) = (intptr_t) esp;
// Llast_SP will be same as SP as there is no adapter space // 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(Llast_SP) = (intptr_t) interpreter_frame->sp() - STACK_BIAS;
*interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache();
#ifdef FAST_DISPATCH #ifdef FAST_DISPATCH
*interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table();
#endif #endif
#ifdef ASSERT #ifdef ASSERT
BasicObjectLock* mp = (BasicObjectLock*)monitors; BasicObjectLock* mp = (BasicObjectLock*)monitors;
assert(interpreter_frame->interpreter_frame_method() == method, "method matches"); 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_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(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(((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"); assert(interpreter_frame->interpreter_frame_tos_address()-1 == esp, "esp matches");
// check bounds // check bounds
intptr_t* lo = interpreter_frame->sp() + (frame::memory_parameter_word_sp_offset - 1); intptr_t* lo = interpreter_frame->sp() + (frame::memory_parameter_word_sp_offset - 1);
intptr_t* hi = interpreter_frame->fp() - rounded_vm_local_words; intptr_t* hi = interpreter_frame->fp() - rounded_vm_local_words;
assert(lo < monitors && montop <= hi, "monitors in bounds"); assert(lo < monitors && montop <= hi, "monitors in bounds");
assert(lo <= esp && esp < monitors, "esp in bounds"); assert(lo <= esp && esp < monitors, "esp in bounds");
#endif // ASSERT #endif // ASSERT
}
return raw_frame_size;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------

View File

@ -288,7 +288,7 @@ void LIR_Assembler::osr_entry() {
// build frame // build frame
ciMethod* m = compilation()->method(); 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 // OSR buffer is
// //
@ -376,7 +376,7 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) {
} }
// This specifies the rsp decrement needed to build the frame // 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! // if rounding, must let FrameMap know!
// The frame_map records size in slots (32bit word) // The frame_map records size in slots (32bit word)

View File

@ -349,13 +349,14 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
} }
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. // Make sure there is enough stack space for this method's activation.
// Note that we do this before doing an enter(). This matches the // Note that we do this before doing an enter(). This matches the
// ordering of C2's stack overflow check / rsp decrement and allows // ordering of C2's stack overflow check / rsp decrement and allows
// the SharedRuntime stack overflow handling to be consistent // the SharedRuntime stack overflow handling to be consistent
// between the two compilers. // between the two compilers.
generate_stack_overflow_check(frame_size_in_bytes); generate_stack_overflow_check(bang_size_in_bytes);
push(rbp); push(rbp);
#ifdef TIERED #ifdef TIERED

View File

@ -2342,29 +2342,42 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
"Stack top out of range"); "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"); static int frame_size_helper(int max_stack,
// NOTE this code must exactly mimic what InterpreterGenerator::generate_compute_interpreter_state() int tempcount,
// does as far as allocating an interpreter frame. int moncount,
// If interpreter_frame!=NULL, set up the method, locals, and monitors. int callee_param_count,
// The frame interpreter_frame, if not NULL, is guaranteed to be the right size, int callee_locals,
// as determined by a previous call to this method. bool is_top_frame,
// It is also guaranteed to be walkable even though it is in a skeletal state 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: 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 // Calculate the amount our frame will be adjust by the callee. For top frame
// this is zero. // this is zero.
@ -2374,87 +2387,102 @@ int AbstractInterpreter::layout_activation(Method* method,
// to it. So it ignores last_frame_adjust value. Seems suspicious as far // to it. So it ignores last_frame_adjust value. Seems suspicious as far
// as getting sender_sp correct. // as getting sender_sp correct.
int extra_locals_size = (callee_locals - callee_param_count) * BytesPerWord; int unused_monitor_size = 0;
int monitor_size = sizeof(BasicObjectLock) * moncount; 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;
}
// First calculate the frame size without any java expression stack void AbstractInterpreter::layout_activation(Method* method,
int short_frame_size = size_activation_helper(extra_locals_size, int tempcount, //
monitor_size); 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) {
// Now with full size expression stack assert(popframe_extra_args == 0, "FIX ME");
int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord; // 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.
// and now with only live portion of the expression stack int monitor_size = 0;
short_frame_size = short_frame_size + tempcount * BytesPerWord; 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);
// 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) {
#ifdef ASSERT #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 #endif
// MUCHO HACK // MUCHO HACK
intptr_t* frame_bottom = (intptr_t*) ((intptr_t)interpreter_frame->sp() - (full_frame_size - frame_size)); intptr_t* frame_bottom = (intptr_t*) ((intptr_t)interpreter_frame->sp() - (full_frame_size - frame_size));
/* Now fillin the interpreterState object */ /* Now fillin the interpreterState object */
// The state object is the first thing on the frame and easily located // The state object is the first thing on the frame and easily located
interpreterState cur_state = (interpreterState) ((intptr_t)interpreter_frame->fp() - sizeof(BytecodeInterpreter)); 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 // 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 // confusing rounding at the callee to account for. We can trivially locate
// our locals based on the current fp(). // our locals based on the current fp().
// Note: the + 2 is for handling the "static long no_params() method" issue. // Note: the + 2 is for handling the "static long no_params() method" issue.
// (too bad I don't really remember that issue well...) // (too bad I don't really remember that issue well...)
intptr_t* locals; intptr_t* locals;
// If the caller is interpreted we need to make sure that locals points to the first // 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. // 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 // 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 // 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 // simpler if we simply stored the result in the BytecodeInterpreter object and let the c++ code
// adjust the stack?? HMMM QQQ // adjust the stack?? HMMM QQQ
// //
if (caller->is_interpreted_frame()) { if (caller->is_interpreted_frame()) {
// locals must agree with the caller because it will be used to set the // locals must agree with the caller because it will be used to set the
// caller's tos when we return. // caller's tos when we return.
interpreterState prev = caller->get_interpreterState(); interpreterState prev = caller->get_interpreterState();
// stack() is prepushed. // stack() is prepushed.
locals = prev->stack() + method->size_of_parameters(); locals = prev->stack() + method->size_of_parameters();
// locals = caller->unextended_sp() + (method->size_of_parameters() - 1); // locals = caller->unextended_sp() + (method->size_of_parameters() - 1);
if (locals != interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2) { if (locals != interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2) {
// os::breakpoint(); // 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;
} }
} else {
intptr_t* monitor_base = (intptr_t*) cur_state; // this is where a c2i would have placed locals (except for the +2)
intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); locals = interpreter_frame->fp() + frame::sender_sp_offset + (method->max_locals() - 1) + 2;
/* +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());
} }
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) { bool AbstractInterpreter::can_be_compiled(methodHandle m) {

View File

@ -1051,7 +1051,7 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) {
// was post-decremented.) Skip this address by starting at i=1, and // 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 // touch a few more pages below. N.B. It is important to touch all
// the way down to and including i=StackShadowPages. // 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 // this could be any sized move but this is can be a debugging crumb
// so the bigger the better. // so the bigger the better.
movptr(Address(tmp, (-i*os::vm_page_size())), size ); movptr(Address(tmp, (-i*os::vm_page_size())), size );
@ -6093,7 +6093,7 @@ void MacroAssembler::reinit_heapbase() {
// C2 compiled method's prolog code. // 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 // WARNING: Initial instruction MUST be 5 bytes or longer so that
// NativeJump::patch_verified_entry will be able to patch out the entry // NativeJump::patch_verified_entry will be able to patch out the entry
@ -6101,18 +6101,20 @@ void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode
// the frame allocation can be either 3 or 6 bytes. So if we don't do // 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 // stack bang then we must use the 6 byte frame allocation even if
// we have no frame. :-( // 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return addr // Remove word for return addr
framesize -= wordSize; framesize -= wordSize;
stack_bang_size -= wordSize;
// Calls to C2R adapters often do not accept exceptional returns. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be careful, because // 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 // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (stack_bang) { if (stack_bang_size > 0) {
generate_stack_overflow_check(framesize); generate_stack_overflow_check(stack_bang_size);
// We always push rbp, so that on return to interpreter rbp, will be // We always push rbp, so that on return to interpreter rbp, will be
// restored correctly and we can correct the stack. // restored correctly and we can correct the stack.

View File

@ -1170,7 +1170,7 @@ public:
void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } 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. // 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'. // clear memory of size 'cnt' qwords, starting at 'base'.
void clear_mem(Register base, Register cnt, Register rtmp); void clear_mem(Register base, Register cnt, Register rtmp);

View File

@ -3014,11 +3014,15 @@ void SharedRuntime::generate_deopt_blob() {
// restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) // 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())); __ 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) { if (UseStackBanging) {
__ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes()));
__ bang_stack_size(rbx, rcx); __ bang_stack_size(rbx, rcx);
} }
#endif
// Load array of frame pcs into ECX // Load array of frame pcs into ECX
__ movptr(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); __ movptr(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()));
@ -3240,12 +3244,15 @@ void SharedRuntime::generate_uncommon_trap_blob() {
// restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) // 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())); __ 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) { if (UseStackBanging) {
__ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes()));
__ bang_stack_size(rbx, rcx); __ bang_stack_size(rbx, rcx);
} }
#endif
// Load array of frame pcs into ECX // Load array of frame pcs into ECX
__ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); __ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()));

View File

@ -3484,11 +3484,15 @@ void SharedRuntime::generate_deopt_blob() {
// restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) // 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())); __ 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) { if (UseStackBanging) {
__ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes()));
__ bang_stack_size(rbx, rcx); __ bang_stack_size(rbx, rcx);
} }
#endif
// Load address of array of frame pcs into rcx // Load address of array of frame pcs into rcx
__ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()));
@ -3682,11 +3686,15 @@ void SharedRuntime::generate_uncommon_trap_blob() {
// restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) // 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())); __ 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) { if (UseStackBanging) {
__ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes()));
__ bang_stack_size(rbx, rcx); __ bang_stack_size(rbx, rcx);
} }
#endif
// Load address of array of frame pcs into rcx (address*) // Load address of array of frame pcs into rcx (address*)
__ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()));

View File

@ -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

View File

@ -1686,91 +1686,6 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
return overhead_size + method_stack + stub_code; 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 // Exceptions

View File

@ -1695,87 +1695,6 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
return (overhead_size + method_stack + stub_code); 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 // Exceptions

View File

@ -512,14 +512,15 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
Compile* C = ra_->C; 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove wordSize for return addr which is already pushed. // Remove wordSize for return addr which is already pushed.
framesize -= wordSize; framesize -= wordSize;
if (C->need_stack_bang(framesize)) { if (C->need_stack_bang(bangsize)) {
framesize -= wordSize; framesize -= wordSize;
st->print("# stack bang"); st->print("# stack bang (%d bytes)", bangsize);
st->print("\n\t"); st->print("\n\t");
st->print("PUSH EBP\t# Save EBP"); st->print("PUSH EBP\t# Save EBP");
if (framesize) { if (framesize) {
@ -563,9 +564,10 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes();
__ verified_entry(framesize, C->need_stack_bang(framesize), C->in_24_bit_fp_mode()); __ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode());
C->set_frame_complete(cbuf.insts_size()); C->set_frame_complete(cbuf.insts_size());
@ -589,7 +591,7 @@ int MachPrologNode::reloc() const {
#ifndef PRODUCT #ifndef PRODUCT
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
Compile *C = ra_->C; 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;
@ -629,7 +631,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;
@ -663,7 +665,7 @@ uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
if (C->max_vector_size() > 16) size += 3; // vzeroupper if (C->max_vector_size() > 16) size += 3; // vzeroupper
if (do_polling() && C->is_method_compilation()) size += 6; 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;

View File

@ -713,14 +713,15 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
Compile* C = ra_->C; 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove wordSize for return addr which is already pushed. // Remove wordSize for return addr which is already pushed.
framesize -= wordSize; framesize -= wordSize;
if (C->need_stack_bang(framesize)) { if (C->need_stack_bang(bangsize)) {
framesize -= wordSize; framesize -= wordSize;
st->print("# stack bang"); st->print("# stack bang (%d bytes)", bangsize);
st->print("\n\t"); st->print("\n\t");
st->print("pushq rbp\t# Save rbp"); st->print("pushq rbp\t# Save rbp");
if (framesize) { if (framesize) {
@ -751,9 +752,10 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes();
__ verified_entry(framesize, C->need_stack_bang(framesize), false); __ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, false);
C->set_frame_complete(cbuf.insts_size()); C->set_frame_complete(cbuf.insts_size());
@ -786,7 +788,7 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
st->cr(); st->print("\t"); 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"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return adr already pushed // Remove word for return adr already pushed
// and RBP // and RBP
@ -822,7 +824,7 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
__ vzeroupper(); __ vzeroupper();
} }
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return adr already pushed // Remove word for return adr already pushed
// and RBP // and RBP

View File

@ -916,17 +916,32 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) {
return (InterpreterFrame *) fp; return (InterpreterFrame *) fp;
} }
int AbstractInterpreter::layout_activation(Method* method, int AbstractInterpreter::size_activation(int max_stack,
int tempcount, int tempcount,
int popframe_extra_args, int extra_args,
int moncount, int moncount,
int caller_actual_parameters, int callee_param_count,
int callee_param_count, int callee_locals,
int callee_locals, bool is_top_frame) {
frame* caller, int header_words = InterpreterFrame::header_words;
frame* interpreter_frame, int monitor_words = moncount * frame::interpreter_frame_monitor_size();
bool is_top_frame, int stack_words = is_top_frame ? max_stack : tempcount;
bool is_bottom_frame) { 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(popframe_extra_args == 0, "what to do?");
assert(!is_top_frame || (!callee_locals && !callee_param_count), assert(!is_top_frame || (!callee_locals && !callee_param_count),
"top frame should have no caller"); "top frame should have no caller");
@ -935,39 +950,31 @@ int AbstractInterpreter::layout_activation(Method* method,
// does (the full InterpreterFrame::build, that is, not the // does (the full InterpreterFrame::build, that is, not the
// one that creates empty frames for the deoptimizer). // one that creates empty frames for the deoptimizer).
// //
// If interpreter_frame is not NULL then it will be filled in. // interpreter_frame will be filled in. It's size is determined by
// It's size is determined by a previous call to this method, // a previous call to the size_activation() method,
// so it should be correct.
// //
// Note that tempcount is the current size of the expression // Note that tempcount is the current size of the expression
// stack. For top most frames we will allocate a full sized // stack. For top most frames we will allocate a full sized
// expression stack and not the trimmed version that non-top // expression stack and not the trimmed version that non-top
// frames have. // frames have.
int header_words = InterpreterFrame::header_words;
int monitor_words = moncount * frame::interpreter_frame_monitor_size(); int monitor_words = moncount * frame::interpreter_frame_monitor_size();
int stack_words = is_top_frame ? method->max_stack() : tempcount; intptr_t *locals = interpreter_frame->fp() + method->max_locals();
int callee_extra_locals = callee_locals - callee_param_count; 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;
if (interpreter_frame) { BytecodeInterpreter::layout_interpreterState(istate,
intptr_t *locals = interpreter_frame->fp() + method->max_locals(); caller,
interpreterState istate = interpreter_frame->get_interpreterState(); NULL,
intptr_t *monitor_base = (intptr_t*) istate; method,
intptr_t *stack_base = monitor_base - monitor_words; locals,
intptr_t *stack = stack_base - tempcount - 1; stack,
stack_base,
BytecodeInterpreter::layout_interpreterState(istate, monitor_base,
caller, NULL,
NULL, is_top_frame);
method,
locals,
stack,
stack_base,
monitor_base,
NULL,
is_top_frame);
}
return header_words + monitor_words + stack_words + callee_extra_locals;
} }
void BytecodeInterpreter::layout_interpreterState(interpreterState istate, void BytecodeInterpreter::layout_interpreterState(interpreterState istate,

View File

@ -546,6 +546,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
, _code(buffer_blob) , _code(buffer_blob)
, _has_access_indexed(false) , _has_access_indexed(false)
, _current_instruction(NULL) , _current_instruction(NULL)
, _interpreter_frame_size(0)
#ifndef PRODUCT #ifndef PRODUCT
, _last_instruction_printed(NULL) , _last_instruction_printed(NULL)
#endif // PRODUCT #endif // PRODUCT

View File

@ -88,6 +88,7 @@ class Compilation: public StackObj {
CodeOffsets _offsets; CodeOffsets _offsets;
CodeBuffer _code; CodeBuffer _code;
bool _has_access_indexed; bool _has_access_indexed;
int _interpreter_frame_size; // Stack space needed in case of a deoptimization
// compilation helpers // compilation helpers
void initialize(); void initialize();
@ -262,6 +263,18 @@ class Compilation: public StackObj {
// Dump inlining replay data to the stream. // Dump inlining replay data to the stream.
void dump_inline_data(outputStream* out) { /* do nothing now */ } 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;
}
}; };

View File

@ -227,8 +227,38 @@ void CodeEmitInfo::add_register_oop(LIR_Opr opr) {
_oop_map->set_oop(name); _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 // Implementation of IR

View File

@ -284,6 +284,8 @@ class CodeEmitInfo: public CompilationResourceObj {
bool is_method_handle_invoke() const { return _is_method_handle_invoke; } bool is_method_handle_invoke() const { return _is_method_handle_invoke; }
void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; }
int interpreter_frame_size() const;
}; };

View File

@ -190,6 +190,13 @@ address LIR_Assembler::pc() const {
return _masm->pc(); 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) { void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) {
for (int i = 0; i < info_list->length(); i++) { for (int i = 0; i < info_list->length(); i++) {
@ -797,7 +804,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
void LIR_Assembler::build_frame() { 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());
} }

View File

@ -132,7 +132,8 @@ class LIR_Assembler: public CompilationResourceObj {
int code_offset() const; int code_offset() const;
address pc() 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 // test for constants which can be encoded directly in instructions
static bool is_small_constant(LIR_Opr opr); static bool is_small_constant(LIR_Opr opr);

View File

@ -2451,6 +2451,9 @@ void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &vis
CodeEmitInfo* info = visitor.info_at(i); CodeEmitInfo* info = visitor.info_at(i);
OopMap* oop_map = first_oop_map; 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()) { if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
// this info has a different number of locks then the precomputed oop map // this info has a different number of locks then the precomputed oop map
// (possible for lock and unlock instructions) -> compute oop map with // (possible for lock and unlock instructions) -> compute oop map with

View File

@ -39,7 +39,7 @@ class C1_MacroAssembler: public MacroAssembler {
void explicit_null_check(Register base); void explicit_null_check(Register base);
void inline_cache_check(Register receiver, Register iCache); 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 remove_frame(int frame_size_in_bytes);
void unverified_entry(Register receiver, Register ic_klass); void unverified_entry(Register receiver, Register ic_klass);

View File

@ -80,6 +80,7 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
_code_size = h_m()->code_size(); _code_size = h_m()->code_size();
_intrinsic_id = h_m()->intrinsic_id(); _intrinsic_id = h_m()->intrinsic_id();
_handler_count = h_m()->exception_table_length(); _handler_count = h_m()->exception_table_length();
_size_of_parameters = h_m()->size_of_parameters();
_uses_monitors = h_m()->access_flags().has_monitor_bytecodes(); _uses_monitors = h_m()->access_flags().has_monitor_bytecodes();
_balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching(); _balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
_is_c1_compilable = !h_m()->is_not_c1_compilable(); _is_c1_compilable = !h_m()->is_not_c1_compilable();

View File

@ -71,6 +71,7 @@ class ciMethod : public ciMetadata {
int _interpreter_invocation_count; int _interpreter_invocation_count;
int _interpreter_throwout_count; int _interpreter_throwout_count;
int _instructions_size; int _instructions_size;
int _size_of_parameters;
bool _uses_monitors; bool _uses_monitors;
bool _balanced_monitors; bool _balanced_monitors;
@ -166,6 +167,7 @@ class ciMethod : public ciMetadata {
int exception_table_length() const { check_is_loaded(); return _handler_count; } 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_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; }
int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_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. // Code size for inlining decisions.
int code_size_for_inlining(); int code_size_for_inlining();
@ -241,7 +243,6 @@ class ciMethod : public ciMetadata {
ciField* get_field_at_bci( int bci, bool &will_link); ciField* get_field_at_bci( int bci, bool &will_link);
ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature); ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
// Given a certain calling environment, find the monomorphic target // Given a certain calling environment, find the monomorphic target
// for the call. Return NULL if the call is not monomorphic in // for the call. Return NULL if the call is not monomorphic in
// its calling environment. // its calling environment.

View File

@ -181,30 +181,16 @@ class AbstractInterpreter: AllStatic {
// Deoptimization should reexecute this bytecode // Deoptimization should reexecute this bytecode
static bool bytecode_should_reexecute(Bytecodes::Code code); static bool bytecode_should_reexecute(Bytecodes::Code code);
// share implementation of size_activation and layout_activation: // deoptimization support
static int size_activation(Method* method, static int size_activation(int max_stack,
int temps, int temps,
int popframe_args, int extra_args,
int monitors, int monitors,
int caller_actual_parameters,
int callee_params, int callee_params,
int callee_locals, int callee_locals,
bool is_top_frame, 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);
}
static int layout_activation(Method* method, static void layout_activation(Method* method,
int temps, int temps,
int popframe_args, int popframe_args,
int monitors, int monitors,

View File

@ -608,6 +608,39 @@ void JVMState::adapt_position(int delta) {
} }
} }
// 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 uint CallNode::cmp( const Node &n ) const
{ return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; }

View File

@ -300,6 +300,7 @@ public:
JVMState* clone_shallow(Compile* C) const; // retains uncloned caller JVMState* clone_shallow(Compile* C) const; // retains uncloned caller
void set_map_deep(SafePointNode *map);// reset map for all callers 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. void adapt_position(int delta); // Adapt offsets in in-array after adding an edge.
int interpreter_frame_size() const;
#ifndef PRODUCT #ifndef PRODUCT
void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const; void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const;

View File

@ -440,6 +440,14 @@ int Compile::frame_size_in_words() const {
return words; 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--------------------------------- //------------------------------CompileWrapper---------------------------------
class CompileWrapper : public StackObj { class CompileWrapper : public StackObj {
@ -664,7 +672,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_print_inlining_list(NULL), _print_inlining_list(NULL),
_print_inlining_stream(NULL), _print_inlining_stream(NULL),
_print_inlining_idx(0), _print_inlining_idx(0),
_preserve_jvm_state(0) { _preserve_jvm_state(0),
_interpreter_frame_size(0) {
C = this; C = this;
CompileWrapper cw(this); CompileWrapper cw(this);
@ -969,7 +978,8 @@ Compile::Compile( ciEnv* ci_env,
_print_inlining_stream(NULL), _print_inlining_stream(NULL),
_print_inlining_idx(0), _print_inlining_idx(0),
_preserve_jvm_state(0), _preserve_jvm_state(0),
_allowed_reasons(0) { _allowed_reasons(0),
_interpreter_frame_size(0) {
C = this; C = this;
#ifndef PRODUCT #ifndef PRODUCT
@ -3078,8 +3088,12 @@ void Compile::final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_
Node* m = n->in(i); Node* m = n->in(i);
++i; ++i;
if (m != NULL && !frc._visited.test_set(m->_idx)) { 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); sfpt.push(m);
}
cnt = m->req(); cnt = m->req();
nstack.push(n, i); // put on stack parent and next input's index nstack.push(n, i); // put on stack parent and next input's index
n = m; n = m;

View File

@ -484,6 +484,7 @@ class Compile : public Phase {
RegMask _FIRST_STACK_mask; // All stack slots usable for spills (depends on frame layout) RegMask _FIRST_STACK_mask; // All stack slots usable for spills (depends on frame layout)
Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin
void* _indexSet_free_block_list; // free list of IndexSet bit blocks void* _indexSet_free_block_list; // free list of IndexSet bit blocks
int _interpreter_frame_size;
uint _node_bundling_limit; uint _node_bundling_limit;
Bundle* _node_bundling_base; // Information for instruction bundling Bundle* _node_bundling_base; // Information for instruction bundling
@ -941,6 +942,7 @@ class Compile : public Phase {
PhaseRegAlloc* regalloc() { return _regalloc; } PhaseRegAlloc* regalloc() { return _regalloc; }
int frame_slots() const { return _frame_slots; } 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_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; } RegMask& FIRST_STACK_mask() { return _FIRST_STACK_mask; }
Arena* indexSet_arena() { return _indexSet_arena; } Arena* indexSet_arena() { return _indexSet_arena; }
void* indexSet_free_block_list() { return _indexSet_free_block_list; } void* indexSet_free_block_list() { return _indexSet_free_block_list; }
@ -952,6 +954,13 @@ class Compile : public Phase {
bool need_stack_bang(int frame_size_in_bytes) const; bool need_stack_bang(int frame_size_in_bytes) const;
bool need_register_stack_bang() 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_matcher(Matcher* m) { _matcher = m; }
//void set_regalloc(PhaseRegAlloc* ra) { _regalloc = ra; } //void set_regalloc(PhaseRegAlloc* ra) { _regalloc = ra; }
void set_indexSet_arena(Arena* a) { _indexSet_arena = a; } void set_indexSet_arena(Arena* a) { _indexSet_arena = a; }

View File

@ -165,8 +165,13 @@ bool Compile::need_stack_bang(int frame_size_in_bytes) const {
// Determine if we need to generate a stack overflow check. // Determine if we need to generate a stack overflow check.
// Do it if the method is not a stub function and // Do it if the method is not a stub function and
// has java calls or has frame size > vm_page_size/8. // 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 && 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 { bool Compile::need_register_stack_bang() const {

View File

@ -420,15 +420,9 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
// frame[number_of_frames - 1 ] = on_stack_size(youngest) // frame[number_of_frames - 1 ] = on_stack_size(youngest)
// frame[number_of_frames - 2 ] = on_stack_size(sender(youngest)) // frame[number_of_frames - 2 ] = on_stack_size(sender(youngest))
// frame[number_of_frames - 3 ] = on_stack_size(sender(sender(youngest))) // frame[number_of_frames - 3 ] = on_stack_size(sender(sender(youngest)))
int caller_parms = callee_parameters; frame_sizes[number_of_frames - 1 - index] = BytesPerWord * array->element(index)->on_stack_size(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,
callee_locals, callee_locals,
index == 0, index == 0,
index == array->frames() - 1,
popframe_extra_args); popframe_extra_args);
// This pc doesn't have to be perfect just good enough to identify the frame // This pc doesn't have to be perfect just good enough to identify the frame
// as interpreted so the skeleton frame will be walkable // as interpreted so the skeleton frame will be walkable

View File

@ -775,10 +775,13 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
// going to be unwound. Dispatch to a shared runtime stub // going to be unwound. Dispatch to a shared runtime stub
// which will cause the StackOverflowError to be fabricated // which will cause the StackOverflowError to be fabricated
// and processed. // and processed.
// For stack overflow in deoptimization blob, cleanup thread. // Stack overflow should never occur during deoptimization:
if (thread->deopt_mark() != NULL) { // the compiled method bangs the stack by as much as the
Deoptimization::cleanup_deopt_info(thread, NULL); // 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); Events::log_exception(thread, "StackOverflowError at " INTPTR_FORMAT, pc);
return StubRoutines::throw_StackOverflowError_entry(); return StubRoutines::throw_StackOverflowError_entry();
} }

View File

@ -418,24 +418,20 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
} }
int vframeArrayElement::on_stack_size(int caller_actual_parameters, int vframeArrayElement::on_stack_size(int callee_parameters,
int callee_parameters,
int callee_locals, int callee_locals,
bool is_top_frame, bool is_top_frame,
bool is_bottom_frame,
int popframe_extra_stack_expression_els) const { int popframe_extra_stack_expression_els) const {
assert(method()->max_locals() == locals()->size(), "just checking"); assert(method()->max_locals() == locals()->size(), "just checking");
int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors(); int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors();
int temps = expressions()->size(); int temps = expressions()->size();
return Interpreter::size_activation(method(), return Interpreter::size_activation(method()->max_stack(),
temps + callee_parameters, temps + callee_parameters,
popframe_extra_stack_expression_els, popframe_extra_stack_expression_els,
locks, locks,
caller_actual_parameters,
callee_parameters, callee_parameters,
callee_locals, callee_locals,
is_top_frame, is_top_frame);
is_bottom_frame);
} }

View File

@ -85,10 +85,8 @@ class vframeArrayElement : public _ValueObj {
// Returns the on stack word size for this frame // Returns the on stack word size for this frame
// callee_parameters is the number of callee locals residing inside this frame // callee_parameters is the number of callee locals residing inside this frame
int on_stack_size(int caller_actual_parameters, int on_stack_size(int callee_parameters,
int callee_parameters,
int callee_locals, int callee_locals,
bool is_bottom_frame,
bool is_top_frame, bool is_top_frame,
int popframe_extra_stack_expression_els) const; int popframe_extra_stack_expression_els) const;

View File

@ -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");
}
}