提交 e7cc7c5c 编写于 作者: K kamg

6991315: RedefineClasses fails with java.lang.VerifyError

Summary: Repair stackmap table attribute when relocating bytecode
Reviewed-by: acorn, never
上级 35c8adf4
此差异已折叠。
......@@ -3601,7 +3601,9 @@ relocInfo_<arch>.hpp generate_platform_dependent_include
relocator.cpp bytecodes.hpp
relocator.cpp handles.inline.hpp
relocator.cpp oop.inline.hpp
relocator.cpp oopFactory.hpp
relocator.cpp relocator.hpp
relocator.cpp stackMapTableFormat.hpp
relocator.cpp universe.inline.hpp
relocator.hpp bytecodes.hpp
......@@ -3908,6 +3910,8 @@ stackMapTable.hpp globalDefinitions.hpp
stackMapTable.hpp methodOop.hpp
stackMapTable.hpp stackMapFrame.hpp
stackMapTableFormat.hpp verificationType.hpp
stackValue.cpp debugInfo.hpp
stackValue.cpp frame.inline.hpp
stackValue.cpp handles.inline.hpp
......
......@@ -247,6 +247,10 @@ class methodOopDesc : public oopDesc {
return constMethod()->stackmap_data();
}
void set_stackmap_data(typeArrayOop sd) {
constMethod()->set_stackmap_data(sd);
}
// exception handler table
typeArrayOop exception_table() const
{ return constMethod()->exception_table(); }
......
......@@ -435,6 +435,120 @@ void Relocator::adjust_local_var_table(int bci, int delta) {
}
}
// Create a new array, copying the src array but adding a hole at
// the specified location
static typeArrayOop insert_hole_at(
size_t where, int hole_sz, typeArrayOop src) {
Thread* THREAD = Thread::current();
Handle src_hnd(THREAD, src);
typeArrayOop dst =
oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL);
src = (typeArrayOop)src_hnd();
address src_addr = (address)src->byte_at_addr(0);
address dst_addr = (address)dst->byte_at_addr(0);
memcpy(dst_addr, src_addr, where);
memcpy(dst_addr + where + hole_sz,
src_addr + where, src->length() - where);
return dst;
}
// The width of instruction at "bci" is changing by "delta". Adjust the stack
// map frames.
void Relocator::adjust_stack_map_table(int bci, int delta) {
if (method()->has_stackmap_table()) {
typeArrayOop data = method()->stackmap_data();
// The data in the array is a classfile representation of the stackmap
// table attribute, less the initial u2 tag and u4 attribute_length fields.
stack_map_table_attribute* attr = stack_map_table_attribute::at(
(address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4)));
int count = attr->number_of_entries();
stack_map_frame* frame = attr->entries();
int bci_iter = -1;
bool offset_adjusted = false; // only need to adjust one offset
for (int i = 0; i < count; ++i) {
int offset_delta = frame->offset_delta();
bci_iter += offset_delta;
if (!offset_adjusted && bci_iter > bci) {
int new_offset_delta = offset_delta + delta;
if (frame->is_valid_offset(new_offset_delta)) {
frame->set_offset_delta(new_offset_delta);
} else {
assert(frame->is_same_frame() ||
frame->is_same_frame_1_stack_item_frame(),
"Frame must be one of the compressed forms");
// The new delta exceeds the capacity of the 'same_frame' or
// 'same_frame_1_stack_item_frame' frame types. We need to
// convert these frames to the extended versions, but the extended
// version is bigger and requires more room. So we allocate a
// new array and copy the data, being sure to leave u2-sized hole
// right after the 'frame_type' for the new offset field.
//
// We can safely ignore the reverse situation as a small delta
// can still be used in an extended version of the frame.
size_t frame_offset = (address)frame - (address)data->byte_at_addr(0);
data = insert_hole_at(frame_offset + 1, 2, data);
if (data == NULL) {
return; // out-of-memory?
}
address frame_addr = (address)(data->byte_at_addr(0) + frame_offset);
frame = stack_map_frame::at(frame_addr);
// Now convert the frames in place
if (frame->is_same_frame()) {
same_frame_extended::create_at(frame_addr, new_offset_delta);
} else {
same_frame_1_stack_item_extended::create_at(
frame_addr, new_offset_delta, NULL);
// the verification_info_type should already be at the right spot
}
}
offset_adjusted = true; // needs to be done only once, since subsequent
// values are offsets from the current
}
// The stack map frame may contain verification types, if so we need to
// check and update any Uninitialized type's bci (no matter where it is).
int number_of_types = frame->number_of_types();
verification_type_info* types = frame->types();
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
// Full frame has stack values too
full_frame* ff = frame->as_full_frame();
if (ff != NULL) {
address eol = (address)types;
number_of_types = ff->stack_slots(eol);
types = ff->stack(eol);
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
}
frame = frame->next();
}
method()->set_stackmap_data(data); // in case it has changed
}
}
bool Relocator::expand_code_array(int delta) {
int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
......@@ -499,6 +613,9 @@ bool Relocator::relocate_code(int bci, int ilen, int delta) {
// And local variable table...
adjust_local_var_table(bci, delta);
// Adjust stack maps
adjust_stack_map_table(bci, delta);
// Relocate the pending change stack...
for (int j = 0; j < _changes->length(); j++) {
ChangeItem* ci = _changes->at(j);
......@@ -641,6 +758,7 @@ bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
memmove(addr_at(bci +1 + new_pad),
addr_at(bci +1 + old_pad),
len * 4);
memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
}
}
return true;
......
......@@ -105,6 +105,7 @@ class Relocator : public ResourceObj {
void adjust_exception_table(int bci, int delta);
void adjust_line_no_table (int bci, int delta);
void adjust_local_var_table(int bci, int delta);
void adjust_stack_map_table(int bci, int delta);
int get_orig_switch_pad (int bci, bool is_lookup_switch);
int rc_instr_len (int bci);
bool expand_code_array (int delta);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册