8028347: Rewriter::scan_method asserts with array oob in RT_Baseline

Fix reversing rewriting for invokespecial

Reviewed-by: jrose, hseigel
This commit is contained in:
Coleen Phillimore 2013-11-15 17:20:22 -05:00
parent 689cc9ddb7
commit 3e62155fec
2 changed files with 29 additions and 27 deletions

View file

@ -70,12 +70,14 @@ void Rewriter::compute_index_maps() {
} }
// Unrewrite the bytecodes if an error occurs. // Unrewrite the bytecodes if an error occurs.
void Rewriter::restore_bytecodes(TRAPS) { void Rewriter::restore_bytecodes() {
int len = _methods->length(); int len = _methods->length();
bool invokespecial_error = false;
for (int i = len-1; i >= 0; i--) { for (int i = len-1; i >= 0; i--) {
Method* method = _methods->at(i); Method* method = _methods->at(i);
scan_method(method, true, CHECK); scan_method(method, true, &invokespecial_error);
assert(!invokespecial_error, "reversing should not get an invokespecial error");
} }
} }
@ -160,22 +162,21 @@ void Rewriter::rewrite_member_reference(address bcp, int offset, bool reverse) {
// These cannot share cpCache entries. It's unclear if all invokespecial to // These cannot share cpCache entries. It's unclear if all invokespecial to
// InterfaceMethodrefs would resolve to the same thing so a new cpCache entry // InterfaceMethodrefs would resolve to the same thing so a new cpCache entry
// is created for each one. This was added with lambda. // is created for each one. This was added with lambda.
void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, TRAPS) { void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error) {
static int count = 0;
address p = bcp + offset; address p = bcp + offset;
if (!reverse) { if (!reverse) {
int cp_index = Bytes::get_Java_u2(p); int cp_index = Bytes::get_Java_u2(p);
if (_pool->tag_at(cp_index).is_interface_method()) {
int cache_index = add_invokespecial_cp_cache_entry(cp_index); int cache_index = add_invokespecial_cp_cache_entry(cp_index);
if (cache_index != (int)(jushort) cache_index) { if (cache_index != (int)(jushort) cache_index) {
THROW_MSG(vmSymbols::java_lang_InternalError(), *invokespecial_error = true;
"This classfile overflows invokespecial for interfaces "
"and cannot be loaded");
} }
Bytes::put_native_u2(p, cache_index); Bytes::put_native_u2(p, cache_index);
} else { } else {
int cache_index = Bytes::get_native_u2(p); rewrite_member_reference(bcp, offset, reverse);
int cp_index = cp_cache_entry_pool_index(cache_index); }
Bytes::put_Java_u2(p, cp_index); } else {
rewrite_member_reference(bcp, offset, reverse);
} }
} }
@ -329,7 +330,7 @@ void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide,
// Rewrites a method given the index_map information // Rewrites a method given the index_map information
void Rewriter::scan_method(Method* method, bool reverse, TRAPS) { void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_error) {
int nof_jsrs = 0; int nof_jsrs = 0;
bool has_monitor_bytecodes = false; bool has_monitor_bytecodes = false;
@ -391,15 +392,7 @@ void Rewriter::scan_method(Method* method, bool reverse, TRAPS) {
} }
case Bytecodes::_invokespecial : { case Bytecodes::_invokespecial : {
int offset = prefix_length + 1; rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
address p = bcp + offset;
int cp_index = Bytes::get_Java_u2(p);
// InterfaceMethodref
if (_pool->tag_at(cp_index).is_interface_method()) {
rewrite_invokespecial(bcp, offset, reverse, CHECK);
} else {
rewrite_member_reference(bcp, offset, reverse);
}
break; break;
} }
@ -496,11 +489,20 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Me
// rewrite methods, in two passes // rewrite methods, in two passes
int len = _methods->length(); int len = _methods->length();
bool invokespecial_error = false;
for (int i = len-1; i >= 0; i--) { for (int i = len-1; i >= 0; i--) {
Method* method = _methods->at(i); Method* method = _methods->at(i);
scan_method(method, false, CHECK); // If you get an error here, scan_method(method, false, &invokespecial_error);
// there is no reversing bytecodes if (invokespecial_error) {
// If you get an error here, there is no reversing bytecodes
// This exception is stored for this class and no further attempt is
// made at verifying or rewriting.
THROW_MSG(vmSymbols::java_lang_InternalError(),
"This classfile overflows invokespecial for interfaces "
"and cannot be loaded");
return;
}
} }
// May have to fix invokedynamic bytecodes if invokestatic/InterfaceMethodref // May have to fix invokedynamic bytecodes if invokestatic/InterfaceMethodref
@ -513,7 +515,7 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Me
// Restore bytecodes to their unrewritten state if there are exceptions // Restore bytecodes to their unrewritten state if there are exceptions
// rewriting bytecodes or allocating the cpCache // rewriting bytecodes or allocating the cpCache
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
restore_bytecodes(CATCH); restore_bytecodes();
return; return;
} }
@ -530,7 +532,7 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Me
// relocating bytecodes. If some are relocated, that is ok because that // relocating bytecodes. If some are relocated, that is ok because that
// doesn't affect constant pool to cpCache rewriting. // doesn't affect constant pool to cpCache rewriting.
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
restore_bytecodes(CATCH); restore_bytecodes();
return; return;
} }
// Method might have gotten rewritten. // Method might have gotten rewritten.

View file

@ -189,18 +189,18 @@ class Rewriter: public StackObj {
void compute_index_maps(); void compute_index_maps();
void make_constant_pool_cache(TRAPS); void make_constant_pool_cache(TRAPS);
void scan_method(Method* m, bool reverse, TRAPS); void scan_method(Method* m, bool reverse, bool* invokespecial_error);
void rewrite_Object_init(methodHandle m, TRAPS); void rewrite_Object_init(methodHandle m, TRAPS);
void rewrite_member_reference(address bcp, int offset, bool reverse); void rewrite_member_reference(address bcp, int offset, bool reverse);
void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse); void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse);
void rewrite_invokedynamic(address bcp, int offset, bool reverse); void rewrite_invokedynamic(address bcp, int offset, bool reverse);
void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse); void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse);
void rewrite_invokespecial(address bcp, int offset, bool reverse, TRAPS); void rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error);
void patch_invokedynamic_bytecodes(); void patch_invokedynamic_bytecodes();
// Revert bytecodes in case of an exception. // Revert bytecodes in case of an exception.
void restore_bytecodes(TRAPS); void restore_bytecodes();
static methodHandle rewrite_jsrs(methodHandle m, TRAPS); static methodHandle rewrite_jsrs(methodHandle m, TRAPS);
public: public: