diff options
Diffstat (limited to 'src/share/vm/classfile')
-rw-r--r-- | src/share/vm/classfile/classFileParser.cpp | 74 | ||||
-rw-r--r-- | src/share/vm/classfile/classFileParser.hpp | 4 | ||||
-rw-r--r-- | src/share/vm/classfile/systemDictionary.cpp | 1 | ||||
-rw-r--r-- | src/share/vm/classfile/verifier.cpp | 130 |
4 files changed, 109 insertions, 100 deletions
diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index b2cec5375..a7f5ab02f 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -1284,42 +1284,38 @@ static void copy_u2_with_conversion(u2* dest, u2* src, int length) { } -typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length, - u4 exception_table_length, - constantPoolHandle cp, - TRAPS) { +u2* ClassFileParser::parse_exception_table(u4 code_length, + u4 exception_table_length, + constantPoolHandle cp, + TRAPS) { ClassFileStream* cfs = stream(); - typeArrayHandle nullHandle; - - // 4-tuples of ints [start_pc, end_pc, handler_pc, catch_type index] - typeArrayOop eh = oopFactory::new_permanent_intArray(exception_table_length*4, CHECK_(nullHandle)); - typeArrayHandle exception_handlers = typeArrayHandle(THREAD, eh); - int index = 0; - cfs->guarantee_more(8 * exception_table_length, CHECK_(nullHandle)); // start_pc, end_pc, handler_pc, catch_type_index - for (unsigned int i = 0; i < exception_table_length; i++) { - u2 start_pc = cfs->get_u2_fast(); - u2 end_pc = cfs->get_u2_fast(); - u2 handler_pc = cfs->get_u2_fast(); - u2 catch_type_index = cfs->get_u2_fast(); - // Will check legal target after parsing code array in verifier. - if (_need_verify) { + u2* exception_table_start = cfs->get_u2_buffer(); + assert(exception_table_start != NULL, "null exception table"); + cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, end_pc, handler_pc, catch_type_index + // Will check legal target after parsing code array in verifier. + if (_need_verify) { + for (unsigned int i = 0; i < exception_table_length; i++) { + u2 start_pc = cfs->get_u2_fast(); + u2 end_pc = cfs->get_u2_fast(); + u2 handler_pc = cfs->get_u2_fast(); + u2 catch_type_index = cfs->get_u2_fast(); guarantee_property((start_pc < end_pc) && (end_pc <= code_length), - "Illegal exception table range in class file %s", CHECK_(nullHandle)); + "Illegal exception table range in class file %s", + CHECK_NULL); guarantee_property(handler_pc < code_length, - "Illegal exception table handler in class file %s", CHECK_(nullHandle)); + "Illegal exception table handler in class file %s", + CHECK_NULL); if (catch_type_index != 0) { guarantee_property(valid_cp_range(catch_type_index, cp->length()) && is_klass_reference(cp, catch_type_index), - "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); + "Catch type in exception table has bad constant type in class file %s", CHECK_NULL); } } - exception_handlers->int_at_put(index++, start_pc); - exception_handlers->int_at_put(index++, end_pc); - exception_handlers->int_at_put(index++, handler_pc); - exception_handlers->int_at_put(index++, catch_type_index); + } else { + cfs->skip_u2_fast(exception_table_length * 4); } - return exception_handlers; + return exception_table_start; } void ClassFileParser::parse_linenumber_table( @@ -1712,6 +1708,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf u4 code_length = 0; u1* code_start = 0; u2 exception_table_length = 0; + u2* exception_table_start = NULL; typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); u2 checked_exceptions_length = 0; u2* checked_exceptions_start = NULL; @@ -1798,7 +1795,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf cfs->guarantee_more(2, CHECK_(nullHandle)); // exception_table_length exception_table_length = cfs->get_u2_fast(); if (exception_table_length > 0) { - exception_handlers = + exception_table_start = parse_exception_table(code_length, exception_table_length, cp, CHECK_(nullHandle)); } @@ -2002,9 +1999,13 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf } // All sizing information for a methodOop is finally available, now create it - methodOop m_oop = oopFactory::new_method(code_length, access_flags, linenumber_table_length, - total_lvt_length, checked_exceptions_length, - oopDesc::IsSafeConc, CHECK_(nullHandle)); + methodOop m_oop = oopFactory::new_method(code_length, access_flags, + linenumber_table_length, + total_lvt_length, + exception_table_length, + checked_exceptions_length, + oopDesc::IsSafeConc, + CHECK_(nullHandle)); methodHandle m (THREAD, m_oop); ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize); @@ -2035,16 +2036,15 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf // Fill in code attribute information m->set_max_stack(max_stack); m->set_max_locals(max_locals); - m->constMethod()->set_stackmap_data(stackmap_data()); /** - * The exception_table field is the flag used to indicate + * The stackmap_data field is the flag used to indicate * that the methodOop and it's associated constMethodOop are partially * initialized and thus are exempt from pre/post GC verification. Once * the field is set, the oops are considered fully initialized so make * sure that the oops can pass verification when this field is set. */ - m->set_exception_table(exception_handlers()); + m->constMethod()->set_stackmap_data(stackmap_data()); // Copy byte codes m->set_code(code_start); @@ -2055,6 +2055,14 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf linenumber_table->buffer(), linenumber_table_length); } + // Copy exception table + if (exception_table_length > 0) { + int size = + exception_table_length * sizeof(ExceptionTableElement) / sizeof(u2); + copy_u2_with_conversion((u2*) m->exception_table_start(), + exception_table_start, size); + } + // Copy checked exceptions if (checked_exceptions_length > 0) { int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2); diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp index de781b2fb..008902eac 100644 --- a/src/share/vm/classfile/classFileParser.hpp +++ b/src/share/vm/classfile/classFileParser.hpp @@ -113,8 +113,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { objArrayHandle methods_parameter_annotations, objArrayHandle methods_default_annotations, TRAPS); - typeArrayHandle parse_exception_table(u4 code_length, u4 exception_table_length, - constantPoolHandle cp, TRAPS); + u2* parse_exception_table(u4 code_length, u4 exception_table_length, + constantPoolHandle cp, TRAPS); void parse_linenumber_table( u4 code_attribute_length, u4 code_length, CompressedLineNumberWriteStream** write_stream, TRAPS); diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp index 74901574d..aca21742f 100644 --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -2771,7 +2771,6 @@ class ClassStatistics: AllStatic { nmethods++; method_size += m->size(); // class loader uses same objArray for empty vectors, so don't count these - if (m->exception_table()->length() != 0) method_size += m->exception_table()->size(); if (m->has_stackmap_table()) { method_size += m->stackmap_data()->size(); } diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp index 905456a2b..e5badd62c 100644 --- a/src/share/vm/classfile/verifier.cpp +++ b/src/share/vm/classfile/verifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -1368,47 +1368,48 @@ char* ClassVerifier::generate_code_data(methodHandle m, u4 code_length, TRAPS) { } void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) { - typeArrayHandle exhandlers (THREAD, _method->exception_table()); + ExceptionTable exhandlers(_method()); + int exlength = exhandlers.length(); constantPoolHandle cp (THREAD, _method->constants()); - if (exhandlers() != NULL) { - for(int i = 0; i < exhandlers->length();) { - u2 start_pc = exhandlers->int_at(i++); - u2 end_pc = exhandlers->int_at(i++); - u2 handler_pc = exhandlers->int_at(i++); - if (start_pc >= code_length || code_data[start_pc] == 0) { - class_format_error("Illegal exception table start_pc %d", start_pc); + for(int i = 0; i < exlength; i++) { + //reacquire the table in case a GC happened + ExceptionTable exhandlers(_method()); + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + u2 handler_pc = exhandlers.handler_pc(i); + if (start_pc >= code_length || code_data[start_pc] == 0) { + class_format_error("Illegal exception table start_pc %d", start_pc); + return; + } + if (end_pc != code_length) { // special case: end_pc == code_length + if (end_pc > code_length || code_data[end_pc] == 0) { + class_format_error("Illegal exception table end_pc %d", end_pc); return; } - if (end_pc != code_length) { // special case: end_pc == code_length - if (end_pc > code_length || code_data[end_pc] == 0) { - class_format_error("Illegal exception table end_pc %d", end_pc); - return; - } - } - if (handler_pc >= code_length || code_data[handler_pc] == 0) { - class_format_error("Illegal exception table handler_pc %d", handler_pc); + } + if (handler_pc >= code_length || code_data[handler_pc] == 0) { + class_format_error("Illegal exception table handler_pc %d", handler_pc); + return; + } + int catch_type_index = exhandlers.catch_type_index(i); + if (catch_type_index != 0) { + VerificationType catch_type = cp_index_to_type( + catch_type_index, cp, CHECK_VERIFY(this)); + VerificationType throwable = + VerificationType::reference_type(vmSymbols::java_lang_Throwable()); + bool is_subclass = throwable.is_assignable_from( + catch_type, this, CHECK_VERIFY(this)); + if (!is_subclass) { + // 4286534: should throw VerifyError according to recent spec change + verify_error( + "Catch type is not a subclass of Throwable in handler %d", + handler_pc); return; } - int catch_type_index = exhandlers->int_at(i++); - if (catch_type_index != 0) { - VerificationType catch_type = cp_index_to_type( - catch_type_index, cp, CHECK_VERIFY(this)); - VerificationType throwable = - VerificationType::reference_type(vmSymbols::java_lang_Throwable()); - bool is_subclass = throwable.is_assignable_from( - catch_type, this, CHECK_VERIFY(this)); - if (!is_subclass) { - // 4286534: should throw VerifyError according to recent spec change - verify_error( - "Catch type is not a subclass of Throwable in handler %d", - handler_pc); - return; - } - } - if (start_pc < min) min = start_pc; - if (end_pc > max) max = end_pc; } + if (start_pc < min) min = start_pc; + if (end_pc > max) max = end_pc; } } @@ -1474,35 +1475,36 @@ u2 ClassVerifier::verify_stackmap_table(u2 stackmap_index, u2 bci, void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame, StackMapTable* stackmap_table, TRAPS) { constantPoolHandle cp (THREAD, _method->constants()); - typeArrayHandle exhandlers (THREAD, _method->exception_table()); - if (exhandlers() != NULL) { - for(int i = 0; i < exhandlers->length();) { - u2 start_pc = exhandlers->int_at(i++); - u2 end_pc = exhandlers->int_at(i++); - u2 handler_pc = exhandlers->int_at(i++); - int catch_type_index = exhandlers->int_at(i++); - if(bci >= start_pc && bci < end_pc) { - u1 flags = current_frame->flags(); - if (this_uninit) { flags |= FLAG_THIS_UNINIT; } - StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); - if (catch_type_index != 0) { - // We know that this index refers to a subclass of Throwable - VerificationType catch_type = cp_index_to_type( - catch_type_index, cp, CHECK_VERIFY(this)); - new_frame->push_stack(catch_type, CHECK_VERIFY(this)); - } else { - VerificationType throwable = - VerificationType::reference_type(vmSymbols::java_lang_Throwable()); - new_frame->push_stack(throwable, CHECK_VERIFY(this)); - } - bool match = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, CHECK_VERIFY(this)); - if (!match) { - verify_error(bci, - "Stack map does not match the one at exception handler %d", - handler_pc); - return; - } + ExceptionTable exhandlers(_method()); + int exlength = exhandlers.length(); + for(int i = 0; i < exlength; i++) { + //reacquire the table in case a GC happened + ExceptionTable exhandlers(_method()); + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + u2 handler_pc = exhandlers.handler_pc(i); + int catch_type_index = exhandlers.catch_type_index(i); + if(bci >= start_pc && bci < end_pc) { + u1 flags = current_frame->flags(); + if (this_uninit) { flags |= FLAG_THIS_UNINIT; } + StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); + if (catch_type_index != 0) { + // We know that this index refers to a subclass of Throwable + VerificationType catch_type = cp_index_to_type( + catch_type_index, cp, CHECK_VERIFY(this)); + new_frame->push_stack(catch_type, CHECK_VERIFY(this)); + } else { + VerificationType throwable = + VerificationType::reference_type(vmSymbols::java_lang_Throwable()); + new_frame->push_stack(throwable, CHECK_VERIFY(this)); + } + bool match = stackmap_table->match_stackmap( + new_frame, handler_pc, true, false, CHECK_VERIFY(this)); + if (!match) { + verify_error(bci, + "Stack map does not match the one at exception handler %d", + handler_pc); + return; } } } |