u2* constMethodOopDesc::localvariable_table_length_addr() const { assert(has_localvariable_table(), "called only if table is present"); if (has_checked_exceptions()) { // If checked_exception present, locate immediately before them. return (u2*) checked_exceptions_start() - 1; } else { // Else, the linenumber table is at the end of the constMethod. return last_u2_element(); } }
void ConstMethod::verify_on(outputStream* st) { guarantee(is_constMethod(), "object must be constMethod"); // Verification can occur during oop construction before the method or // other fields have been initialized. guarantee(method()->is_method(), "should be method"); address m_end = (address)((intptr_t) this + size()); address compressed_table_start = code_end(); guarantee(compressed_table_start <= m_end, "invalid method layout"); address compressed_table_end = compressed_table_start; // Verify line number table if (has_linenumber_table()) { CompressedLineNumberReadStream stream(compressed_linenumber_table()); while (stream.read_pair()) { guarantee(stream.bci() >= 0 && stream.bci() <= code_size(), "invalid bci in line number table"); } compressed_table_end += stream.position(); } guarantee(compressed_table_end <= m_end, "invalid method layout"); // Verify checked exceptions, exception table and local variable tables if (has_method_parameters()) { u2* addr = method_parameters_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); } if (has_checked_exceptions()) { u2* addr = checked_exceptions_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); } if (has_exception_handler()) { u2* addr = exception_table_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); } if (has_localvariable_table()) { u2* addr = localvariable_table_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); } // Check compressed_table_end relative to uncompressed_table_start u2* uncompressed_table_start; if (has_localvariable_table()) { uncompressed_table_start = (u2*) localvariable_table_start(); } else if (has_exception_handler()) { uncompressed_table_start = (u2*) exception_table_start(); } else if (has_checked_exceptions()) { uncompressed_table_start = (u2*) checked_exceptions_start(); } else if (has_method_parameters()) { uncompressed_table_start = (u2*) method_parameters_start(); } else { uncompressed_table_start = (u2*) m_end; } int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end; int max_gap = align_metadata_size(1)*BytesPerWord; guarantee(gap >= 0 && gap < max_gap, "invalid method layout"); }
u2* ConstMethod::exception_table_length_addr() const { assert(has_exception_handler(), "called only if table is present"); if (has_checked_exceptions()) { // If checked_exception present, locate immediately before them. return (u2*) checked_exceptions_start() - 1; } else { if(has_method_parameters()) { // If method parameters present, locate immediately before them. return (u2*)method_parameters_start() - 1; } else { // Else, the exception table is at the end of the constMethod. return has_generic_signature() ? (last_u2_element() - 1) : last_u2_element(); } } }