< prev index next > src/hotspot/cpu/x86/frame_x86.cpp
Print this page
sender_sp = _unextended_sp + _cb->frame_size();
// Is sender_sp safe?
if (!thread->is_in_full_stack_checked((address)sender_sp)) {
return false;
}
- sender_unextended_sp = sender_sp;
// On Intel the return_address is always the word on the stack
sender_pc = (address) *(sender_sp-1);
// Note: frame::sender_sp_offset is only valid for compiled frame
- saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset);
- }
+ intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset);
+ saved_fp = *saved_fp_addr;
+ // Repair the sender sp if this is a method with scalarized inline type args
+ sender_sp = repair_sender_sp(sender_sp, saved_fp_addr);
+ sender_unextended_sp = sender_sp;
+ }
// If the potential sender is the interpreter then we can do some more checking
if (Interpreter::contains(sender_pc)) {
// ebp is always saved in a recognizable place in any code we generate. However
assert(map != NULL, "map must be set");
// frame owned by optimizing compiler
assert(_cb->frame_size() >= 0, "must have non-zero frame size");
intptr_t* sender_sp = unextended_sp() + _cb->frame_size();
- intptr_t* unextended_sp = sender_sp;
- // On Intel the return_address is always the word on the stack
- address sender_pc = (address) *(sender_sp-1);
+ #ifdef ASSERT
+ address sender_pc_copy = (address) *(sender_sp-1);
+ #endif
// This is the saved value of EBP which may or may not really be an FP.
// It is only an FP if the sender is an interpreter frame (or C1?).
intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset);
+ // Repair the sender sp if the frame has been extended
+ sender_sp = repair_sender_sp(sender_sp, saved_fp_addr);
+
+ // On Intel the return_address is always the word on the stack
+ address sender_pc = (address) *(sender_sp-1);
+
+ #ifdef ASSERT
+ if (sender_pc != sender_pc_copy) {
+ // When extending the stack in the callee method entry to make room for unpacking of value
+ // type args, we keep a copy of the sender pc at the expected location in the callee frame.
+ // If the sender pc is patched due to deoptimization, the copy is not consistent anymore.
+ nmethod* nm = CodeCache::find_blob(sender_pc)->as_nmethod();
+ assert(sender_pc == nm->deopt_mh_handler_begin() || sender_pc == nm->deopt_handler_begin(), "unexpected sender pc");
+ }
+ #endif
+
if (map->update_map()) {
// Tell GC to use argument oopmaps for some runtime stubs that need it.
// For C1, the runtime stub might not have oop maps, so set this flag
// outside of update_register_map.
- map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
+ bool caller_args = _cb->caller_must_gc_arguments(map->thread());
+ #ifdef COMPILER1
+ if (!caller_args) {
+ nmethod* nm = _cb->as_nmethod_or_null();
+ if (nm != NULL && nm->is_compiled_by_c1() && nm->method()->has_scalarized_args() &&
+ pc() < nm->verified_inline_entry_point()) {
+ // The VEP and VIEP(RO) of C1-compiled methods call buffer_inline_args_xxx
+ // before doing any argument shuffling, so we need to scan the oops
+ // as the caller passes them.
+ caller_args = true;
+ #ifdef ASSERT
+ NativeCall* call = nativeCall_before(pc());
+ address dest = call->destination();
+ assert(dest == Runtime1::entry_for(Runtime1::buffer_inline_args_no_receiver_id) ||
+ dest == Runtime1::entry_for(Runtime1::buffer_inline_args_id), "unexpected safepoint in entry point");
+ #endif
+ }
+ }
+ #endif
+ map->set_include_argument_oops(caller_args);
if (_cb->oop_maps() != NULL) {
OopMapSet::update_register_map(this, map);
}
// Since the prolog does the save and restore of EBP there is no oopmap
// since if our caller was compiled code there could be live jvm state in it.
update_map_with_saved_link(map, saved_fp_addr);
}
assert(sender_sp != sp(), "must have changed");
- return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
+ return frame(sender_sp, sender_sp, *saved_fp_addr, sender_pc);
}
//------------------------------------------------------------------------------
// frame::sender_raw
frame frame::sender_raw(RegisterMap* map) const {
- // Default is we done have to follow them. The sender_for_xxx will
+ // Default is we don't have to follow them. The sender_for_xxx will
// update it accordingly
map->set_include_argument_oops(false);
if (is_entry_frame()) return sender_for_entry_frame(map);
if (is_optimized_entry_frame()) return sender_for_optimized_entry_frame(map);
tos_addr = (intptr_t*)interpreter_frame_tos_address();
}
switch (type) {
case T_OBJECT :
+ case T_PRIMITIVE_OBJECT:
case T_ARRAY : {
oop obj;
if (method->is_native()) {
obj = cast_to_oop(at(interpreter_frame_oop_temp_offset));
} else {
init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
}
#endif
+ // Check for a method with scalarized inline type arguments that needs
+ // a stack repair and return the repaired sender stack pointer.
+ intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) const {
+ CompiledMethod* cm = _cb->as_compiled_method_or_null();
+ if (cm != NULL && cm->needs_stack_repair()) {
+ // The stack increment resides just below the saved rbp on the stack
+ // and does not account for the return address.
+ intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1);
+ int real_frame_size = ((*real_frame_size_addr) + wordSize) / wordSize;
+ assert(real_frame_size >= _cb->frame_size() && real_frame_size <= 1000000, "invalid frame size");
+ sender_sp = unextended_sp() + real_frame_size;
+ }
+ return sender_sp;
+ }
+
void JavaFrameAnchor::make_walkable(JavaThread* thread) {
// last frame set?
if (last_Java_sp() == NULL) return;
// already walkable?
if (walkable()) return;
< prev index next >