Skip to content
Permalink
Browse files
Fix chunk max_size calculation
  • Loading branch information
pron committed Mar 25, 2021
1 parent cbb8045 commit 3a92f4366a81dbca9bbfc4eb2b71b8390d1a0f26
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 52 deletions.
@@ -87,7 +87,6 @@ inline intptr_t* StackChunkFrameStream<mixed>::unextended_sp_for_interpreter_fra
template <bool mixed>
intptr_t* StackChunkFrameStream<mixed>::next_sp_for_interpreter_frame() const {
assert (mixed && is_interpreted(), "");
// tty->print_cr(">>>> StackChunkFrameStream<mixed>::next_for_interpreter_frame derelativize(frame::interpreter_frame_locals_offset): %p _end: %p", derelativize(frame::interpreter_frame_locals_offset), _end);
return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset;
}

@@ -101,20 +100,18 @@ inline void StackChunkFrameStream<mixed>::next_for_interpreter_frame() {
intptr_t* fp = this->fp();
_unextended_sp = fp + fp[frame::interpreter_frame_sender_sp_offset];
_sp = fp + frame::sender_sp_offset;
// assert (_unextended_sp >= _sp, "fp[frame::interpreter_frame_sender_sp_offset]: %ld", fp[frame::interpreter_frame_sender_sp_offset]);
assert (!is_interpreted() || _unextended_sp == unextended_sp_for_interpreter_frame(), "_unextended_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT, p2i(_unextended_sp), p2i(unextended_sp_for_interpreter_frame()));
}
}

template <bool mixed>
inline int StackChunkFrameStream<mixed>::interpreter_frame_size() const {
assert (mixed && is_interpreted(), "");
InterpreterOopMap mask;
to_frame().interpreted_frame_oop_map(&mask);

// unextended sp to unextended sp
// InterpreterOopMap mask;
// to_frame().interpreted_frame_oop_map(&mask);
// intptr_t* top = derelativize(frame::interpreter_frame_initial_sp_offset) - mask.expression_stack_size();

intptr_t* top = unextended_sp(); // later subtract argsize if callee is interpreted
intptr_t* bottom = derelativize(frame::interpreter_frame_locals_offset) + 1; // the sender's unextended sp: derelativize(frame::interpreter_frame_sender_sp_offset);
intptr_t* top = derelativize(frame::interpreter_frame_initial_sp_offset) - mask.expression_stack_size(); // unextended_sp(); //

// tty->print_cr(">>>> StackChunkFrameStream<mixed>::interpreter_frame_size bottom: %d top: %d size: %d", _chunk->to_offset(bottom - 1) + 1, _chunk->to_offset(top), (int)(bottom - top));
return (int)(bottom - top);
@@ -147,10 +144,11 @@ inline void stackChunkOopDesc::derelativize_frame_pd(frame& fr) const {
if (fr.is_interpreted_frame()) fr.set_fp(derelativize_address(fr.offset_fp()));
}

inline void InstanceStackChunkKlass::relativize(intptr_t* const fp, intptr_t* const hfp, int offset) {
inline void InstanceStackChunkKlass::relativize(intptr_t* const vfp, intptr_t* const hfp, int offset) {
assert (*(hfp + offset) == *(vfp + offset), "vaddr: " INTPTR_FORMAT " *vaddr: " INTPTR_FORMAT " haddr: " INTPTR_FORMAT " *haddr: " INTPTR_FORMAT, p2i(vfp + offset) , *(vfp + offset), p2i(hfp + offset) , *(hfp + offset));
intptr_t* addr = hfp + offset;
intptr_t value = *(intptr_t**)addr - fp;
// tty->print_cr(">>>> relativize offset: %d fp: %p delta: %ld derel: %p", offset, fp, value, *(intptr_t**)addr);
intptr_t value = *(intptr_t**)addr - vfp;
// tty->print_cr(">>>> relativize offset: %d fp: %p delta: %ld derel: %p", offset, vfp, value, *(intptr_t**)addr);
*addr = value;
}

@@ -164,15 +162,19 @@ inline void InstanceStackChunkKlass::relativize_interpreted_frame_metadata(const
intptr_t* vfp = f.fp();
intptr_t* hfp = hf.fp();
assert (hfp == hf.unextended_sp() + (f.fp() - f.unextended_sp()), "");
assert ((*(vfp + frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");

assert ((f.at<false>(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
assert (f.fp() > (intptr_t*)f.at<false>(frame::interpreter_frame_initial_sp_offset), "");

// at(frame::interpreter_frame_last_sp_offset) can be NULL at safepoint preempts
*hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
relativize(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
relativize(vfp, hfp, frame::interpreter_frame_locals_offset);

assert (hf.unextended_sp() <= (intptr_t*)hf.at<true>(frame::interpreter_frame_initial_sp_offset), "");
assert ((hf.fp() - hf.unextended_sp()) == (f.fp() - f.unextended_sp()), "");
assert (hf.unextended_sp() == (intptr_t*)hf.at<true>(frame::interpreter_frame_last_sp_offset), "");
assert (hf.unextended_sp() <= (intptr_t*)hf.at<true>(frame::interpreter_frame_initial_sp_offset), "");
assert (hf.fp() > (intptr_t*)hf.at<true>(frame::interpreter_frame_initial_sp_offset), "");
assert (hf.fp() <= (intptr_t*)hf.at<true>(frame::interpreter_frame_locals_offset), "");
}

inline void InstanceStackChunkKlass::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
@@ -464,19 +464,20 @@ class VerifyStackClosure {
_sp = f.sp();
_cb = f.cb();

int fsize = f.frame_size();
int fsize = f.frame_size() - ((f.is_interpreted() == _callee_interpreted) ? _argsize : 0);
int num_oops = f.num_oops();
assert (num_oops >= 0, "");
// tty->print_cr(">>> fsize: %d f.frame_size(): %d callee_interpreted: %d callee_argsize: %d", fsize, f.frame_size(), _callee_interpreted, _argsize);

_argsize = f.stack_argsize();
_size += fsize;
_argsize = f.is_interpreted() ? 0 : f.stack_argsize();
_num_oops += num_oops;
if (f.is_interpreted()) {
_num_interpreted_frames++;
}

// assert (!chunk->requires_barriers() || num_frames <= chunk->numFrames(), "");
log_develop_trace(jvmcont)("debug_verify_stack_chunk frame: %d sp: %ld pc: " INTPTR_FORMAT " interpreted: %d size: %d oops: %d", _num_frames, f.sp() - _chunk->start_address(), p2i(f.pc()), f.is_interpreted(), fsize, num_oops);
log_develop_trace(jvmcont)("debug_verify_stack_chunk frame: %d sp: %ld pc: " INTPTR_FORMAT " interpreted: %d size: %d argsize: %d oops: %d", _num_frames, f.sp() - _chunk->start_address(), p2i(f.pc()), f.is_interpreted(), fsize, _argsize, num_oops);
if (log_develop_is_enabled(Trace, jvmcont)) f.print_on(tty);
assert (f.pc() != nullptr,
"young: %d chunk->numFrames(): %d num_frames: %d sp: " INTPTR_FORMAT " start: " INTPTR_FORMAT " end: " INTPTR_FORMAT,
@@ -582,25 +583,23 @@ bool InstanceStackChunkKlass::verify(oop obj, size_t* out_size, int* out_oops, i
closure._sp += closure._cb != nullptr ? ((closure._cb->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord) : 0;
}
}
if (!concurrent) {
assert (closure._size <= size, "size: %d closure.size: %d end sp: %ld start sp: %d chunk size: %d argsize: %d", size, closure._size, closure._sp - chunk->start_address(), chunk->sp(), chunk->stack_size(), chunk->argsize());
}

assert (chunk->argsize() == closure._argsize, "chunk->argsize(): %d argsize: %d", chunk->argsize(), closure._argsize);
size += chunk->argsize();
size += closure._num_i2c * align_wiggle();
// TODO R: uncomment assertion below
// assert (chunk->max_size() == size, "max_size(): %d size: %d argsize: %d num_i2c: %d", chunk->max_size(), size, chunk->argsize(), closure._num_i2c);

if (!concurrent) {
assert (closure._size <= size + chunk->argsize() + metadata_words(), "size: %d argsize: %d closure.size: %d end sp: %ld start sp: %d chunk size: %d", size, chunk->argsize(), closure._size, closure._sp - chunk->start_address(), chunk->sp(), chunk->stack_size());
assert (chunk->argsize() == (closure._callee_interpreted ? 0 : closure._argsize), "chunk->argsize(): %d closure.argsize: %d closure.callee_interpreted: %d", chunk->argsize(), closure._argsize, closure._callee_interpreted);

int max_size = closure._size + closure._num_i2c * align_wiggle();
assert (chunk->max_size() == max_size, "max_size(): %d max_size: %d argsize: %d num_i2c: %d", chunk->max_size(), max_size, closure._argsize, closure._num_i2c);

assert (chunk->numFrames() == -1 || closure._num_frames == chunk->numFrames(), "barriers: %d num_frames: %d chunk->numFrames(): %d", chunk->requires_barriers(), closure._num_frames, chunk->numFrames());
assert (chunk->numOops() == -1 || closure._num_oops == chunk->numOops(), "barriers: %d num_oops: %d chunk->numOops(): %d", chunk->requires_barriers(), closure._num_oops, chunk->numOops());
}

if (out_size != nullptr) *out_size += size;
if (out_oops != nullptr) *out_oops += closure._num_oops;
if (out_frames != nullptr) *out_frames += closure._num_frames;
if (out_interpreted_frames != nullptr) *out_interpreted_frames += closure._num_interpreted_frames;
if (out_size != nullptr) *out_size += size;
if (out_oops != nullptr) *out_oops += closure._num_oops;
if (out_frames != nullptr) *out_frames += closure._num_frames;
if (out_interpreted_frames != nullptr) *out_interpreted_frames += closure._num_interpreted_frames;
} else assert (out_size == nullptr && out_oops == nullptr && out_frames == nullptr && out_interpreted_frames == nullptr, "");


return true;
}
@@ -384,6 +384,7 @@ StackChunkFrameStream<mixed>::StackChunkFrameStream(stackChunkOop chunk, bool gc
} else {
_unextended_sp = _sp;
}
assert (_unextended_sp >= _sp - InstanceStackChunkKlass::metadata_words(), "");
// else if (is_compiled()) {
// tty->print_cr(">>>>> XXXX"); os::print_location(tty, (intptr_t)nativeCall_before(pc())->destination());
// assert (NativeCall::is_call_before(pc()) && nativeCall_before(pc()) != nullptr && nativeCall_before(pc())->destination() != nullptr, "");
@@ -413,6 +414,7 @@ StackChunkFrameStream<mixed>::StackChunkFrameStream(stackChunkOop chunk, const f
_sp = f.sp();
if (mixed) {
_unextended_sp = f.unextended_sp();
assert (_unextended_sp >= _sp - InstanceStackChunkKlass::metadata_words(), "");
}
DEBUG_ONLY(else _unextended_sp = nullptr;)
assert (_sp >= chunk->start_address() && _sp <= chunk->start_address() + chunk->stack_size() + InstanceStackChunkKlass::metadata_words(), "");
@@ -447,7 +449,8 @@ inline bool StackChunkFrameStream<mixed>::is_interpreted() const {

template <bool mixed>
inline int StackChunkFrameStream<mixed>::frame_size() const {
return (mixed && is_interpreted()) ? interpreter_frame_size() : cb()->frame_size();
return (mixed && is_interpreted()) ? interpreter_frame_size()
: cb()->frame_size() + stack_argsize();
}

template <bool mixed>
@@ -482,12 +485,14 @@ inline void StackChunkFrameStream<mixed>::next(RegisterMapT* map) {
if (_sp >= _end - InstanceStackChunkKlass::metadata_words()) {
_sp = _end;
}
_unextended_sp = _sp;
_unextended_sp = is_interpreted() ? unextended_sp_for_interpreter_frame() : _sp;
}
assert (_unextended_sp >= _sp - InstanceStackChunkKlass::metadata_words(), "");
} else {
_sp += cb()->frame_size();
}

assert (!is_interpreted() || _unextended_sp == unextended_sp_for_interpreter_frame(), "_unextended_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT, p2i(_unextended_sp), p2i(unextended_sp_for_interpreter_frame()));

get_cb();
update_reg_map_pd(map);
if (safepoint && cb() != nullptr) _oopmap = cb()->oop_map_for_return_address(pc()); // there's no post-call nop and no fast oopmap lookup
@@ -623,6 +628,7 @@ void StackChunkFrameStream<mixed>::handle_deopted() const {
address pc1 = pc();
int oopmap_slot = CodeCache::find_oopmap_slot_fast(pc1);
if (UNLIKELY(oopmap_slot < 0)) { // we could have marked frames for deoptimization in thaw_chunk
// tty->print_cr(">>>> handle_deopted: deopted");
CompiledMethod* cm = cb()->as_compiled_method();
if (cm->is_deopt_pc(pc1)) {
pc1 = orig_pc();
@@ -920,6 +926,9 @@ class OopOopIterateStackClosure {

if (f.is_compiled()) f.handle_deopted(); // because of deopt in thaw; TODO: remove when changing deoptimization

// tty->print_cr(">>>> OopOopIterateStackClosure::do_frame is_compiled: %d return_barrier: %d pc: %p", f.is_compiled(), Continuation::is_return_barrier_entry(f.pc()), f.pc()); f.print_on(tty);
// if (f.is_compiled()) tty->print_cr(">>>> OopOopIterateStackClosure::do_frame nmethod: %p method: %p", f.cb()->as_nmethod(), f.cb()->as_compiled_method()->method());

// if (log_develop_is_enabled(Trace, jvmcont)) cb->print_value_on(tty);

CodeBlob* cb = f.cb();
@@ -965,6 +974,7 @@ void InstanceStackChunkKlass::oop_oop_iterate_stack_bounded(stackChunkOop chunk,
assert (!SafepointSynchronize::is_at_safepoint() || chunk->gc_mode(), "gc_mode: %d is_at_safepoint: %d", chunk->gc_mode(), SafepointSynchronize::is_at_safepoint());
}

// tty->print_cr(">>>> OopOopIterateStackClosure::oop_oop_iterate_stack_bounded");
OopOopIterateStackClosure<concurrent_gc, OopClosureType> frame_closure(chunk, do_destructive_processing, closure);
chunk->iterate_stack(&frame_closure, mr);

@@ -1476,13 +1476,14 @@ class Freeze {
}

NOINLINE freeze_result recurse_freeze_interpreted_frame(frame& f, frame& caller, int callee_argsize, bool callee_interpreted) {
// ResourceMark rm(_thread);
// ResourceMark rm;
// InterpreterOopMap mask;
// f.interpreted_frame_oop_map(&mask);
// int oops = Interpreted::num_oops(f, &mask);
// int oops = Interpreted::num_oops(f, &mask);

{ // TODO PD
intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
assert ((f.at<false>(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
intptr_t* real_unextended_sp = (intptr_t*)f.at<false>(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}

@@ -1492,9 +1493,10 @@ class Freeze {

#ifdef ASSERT
{
ResourceMark rm;
InterpreterOopMap mask;
f.interpreted_frame_oop_map(&mask);
assert (vsp <= Interpreted::frame_top(f, &mask), "vsp: " INTPTR_FORMAT " Interpreted::frame_top: " INTPTR_FORMAT, p2i(vsp), p2i(Interpreted::frame_top(f, &mask)));
assert (vsp <= Interpreted::frame_top(f, &mask), "vsp: " INTPTR_FORMAT " Interpreted::frame_top: " INTPTR_FORMAT, p2i(vsp), p2i(Interpreted::frame_top(f, &mask)));
assert (fsize >= Interpreted::size(f, &mask), "fsize: %d Interpreted::size: %d", fsize, Interpreted::size(f, &mask));
if (fsize > Interpreted::size(f, &mask) + 1) {
log_develop_trace(jvmcont)("III fsize: %d Interpreted::size: %d", fsize, Interpreted::size(f, &mask));
@@ -2200,6 +2202,8 @@ inline bool can_thaw_fast() {
int num_frames = (return_barrier ? 1 : 2);

_stream = StackChunkFrameStream<true>(chunk);
_top_unextended_sp = _stream.unextended_sp();

frame hf = _stream.to_frame();
log_develop_trace(jvmcont)("top_hframe before (thaw):"); if (log_develop_is_enabled(Trace, jvmcont)) hf.print_on<true>(tty);

@@ -2465,14 +2469,12 @@ inline bool can_thaw_fast() {
template<typename FKind>
void finalize_thaw(frame& entry, int argsize) {
stackChunkOop chunk = _cont.tail();

int orig_sp = chunk->sp();

_top_unextended_sp = _stream.unextended_sp();
// assert (is_empty == _cont.is_empty() /* _last_frame.is_empty()*/, "hf.is_empty(cont): %d last_frame.is_empty(): %d ", is_empty, _cont.is_empty()/*_last_frame.is_empty()*/);

OrderAccess::storestore();
if (!_stream.is_done()) {
assert (_stream.sp() >= chunk->sp_address(), "");
chunk->set_sp(chunk->to_offset(_stream.sp()));
chunk->set_pc(_stream.pc());
} else {
@@ -2482,9 +2484,8 @@ inline bool can_thaw_fast() {
}
assert(_stream.is_done() == chunk->is_empty(), "_stream.is_done(): %d chunk->is_empty(): %d", _stream.is_done(), chunk->is_empty());

assert (chunk->sp() >= orig_sp, "");
int delta = chunk->sp() - orig_sp;
log_develop_trace(jvmcont)("sub max_size: %d -- %d", delta, chunk->max_size() - delta);
int delta = _stream.unextended_sp() - _top_unextended_sp;
log_develop_trace(jvmcont)("sub max_size: %d -- %d (unextended_sp: " INTPTR_FORMAT " orig unextended_sp: " INTPTR_FORMAT ")", delta, chunk->max_size() - delta, p2i(_stream.unextended_sp()), p2i(_top_unextended_sp));
chunk->set_max_size(chunk->max_size() - delta);

assert (!_stream.is_done() || chunk->parent() != nullptr || argsize == 0, "");
@@ -2696,13 +2697,8 @@ inline bool can_thaw_fast() {
chunk->reset_counters();
assert (chunk->argsize() == 0, "");
} else {
int orig_sp = chunk->sp();
assert (chunk->sp() >= orig_sp, "");
int delta = chunk->sp() - orig_sp;
log_develop_trace(jvmcont)("sub max_size: %d -- %d", delta, chunk->max_size() - delta);
log_develop_trace(jvmcont)("sub max_size _align_size: %d -- %d", _align_size, chunk->max_size() + _align_size);
delta += _align_size;
chunk->set_max_size(chunk->max_size() - delta);
log_develop_trace(jvmcont)("sub max_size _align_size: %d -- %d", _align_size, chunk->max_size() - _align_size);
chunk->set_max_size(chunk->max_size() - _align_size);
}
assert (chunk->is_empty() == (chunk->max_size() == 0), "chunk->is_empty: %d chunk->max_size: %d", chunk->is_empty(), chunk->max_size());

@@ -1654,7 +1654,7 @@ void FrameValues::print_on(outputStream* st, int min_index, int max_index, intpt
if (relative
&& *fv.location != 0 && *fv.location > -100 && *fv.location < 100
&& (strncmp(fv.description, "interpreter_frame_", 18) == 0 || strstr(fv.description, " method "))) {
st->print_cr(" " INTPTR_FORMAT ": %18d %s", p2i(fv.location), (int)*fv.location, fv.description);
st->print_cr(" " INTPTR_FORMAT ": %18d %s (" INTPTR_FORMAT ")", p2i(fv.location), (int)*fv.location, fv.description, p2i(fv.location + (int)*fv.location));
} else {
st->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", p2i(fv.location), *fv.location, fv.description);
}

0 comments on commit 3a92f43

Please sign in to comment.