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:
parent
bce45e9222
commit
f5adc57f94
@ -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
|
||||||
|
@ -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 &&
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
//
|
//
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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()));
|
||||||
|
@ -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()));
|
||||||
|
124
hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp
Normal file
124
hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp
Normal 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
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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; }
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user