duke@435: /* stefank@2314: * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "oops/constMethodOop.hpp" stefank@2314: #include "oops/methodOop.hpp" duke@435: duke@435: // Static initialization duke@435: const u2 constMethodOopDesc::MAX_IDNUM = 0xFFFE; duke@435: const u2 constMethodOopDesc::UNSET_IDNUM = 0xFFFF; duke@435: duke@435: // How big must this constMethodObject be? duke@435: duke@435: int constMethodOopDesc::object_size(int code_size, duke@435: int compressed_line_number_size, duke@435: int local_variable_table_length, duke@435: int checked_exceptions_length) { duke@435: int extra_bytes = code_size; duke@435: if (compressed_line_number_size > 0) { duke@435: extra_bytes += compressed_line_number_size; duke@435: } duke@435: if (checked_exceptions_length > 0) { duke@435: extra_bytes += sizeof(u2); duke@435: extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement); duke@435: } duke@435: if (local_variable_table_length > 0) { duke@435: extra_bytes += sizeof(u2); duke@435: extra_bytes += duke@435: local_variable_table_length * sizeof(LocalVariableTableElement); duke@435: } duke@435: int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; duke@435: return align_object_size(header_size() + extra_words); duke@435: } duke@435: duke@435: duke@435: // linenumber table - note that length is unknown until decompression, duke@435: // see class CompressedLineNumberReadStream. duke@435: duke@435: u_char* constMethodOopDesc::compressed_linenumber_table() const { duke@435: // Located immediately following the bytecodes. duke@435: assert(has_linenumber_table(), "called only if table is present"); duke@435: return code_end(); duke@435: } duke@435: duke@435: u2* constMethodOopDesc::checked_exceptions_length_addr() const { duke@435: // Located at the end of the constMethod. duke@435: assert(has_checked_exceptions(), "called only if table is present"); duke@435: return last_u2_element(); duke@435: } duke@435: duke@435: u2* constMethodOopDesc::localvariable_table_length_addr() const { duke@435: assert(has_localvariable_table(), "called only if table is present"); duke@435: if (has_checked_exceptions()) { duke@435: // If checked_exception present, locate immediately before them. duke@435: return (u2*) checked_exceptions_start() - 1; duke@435: } else { duke@435: // Else, the linenumber table is at the end of the constMethod. duke@435: return last_u2_element(); duke@435: } duke@435: } duke@435: duke@435: duke@435: // Update the flags to indicate the presence of these optional fields. duke@435: void constMethodOopDesc::set_inlined_tables_length( duke@435: int checked_exceptions_len, duke@435: int compressed_line_number_size, duke@435: int localvariable_table_len) { duke@435: // Must be done in the order below, otherwise length_addr accessors duke@435: // will not work. Only set bit in header if length is positive. duke@435: assert(_flags == 0, "Error"); duke@435: if (compressed_line_number_size > 0) { duke@435: _flags |= _has_linenumber_table; duke@435: } duke@435: if (checked_exceptions_len > 0) { duke@435: _flags |= _has_checked_exceptions; duke@435: *(checked_exceptions_length_addr()) = checked_exceptions_len; duke@435: } duke@435: if (localvariable_table_len > 0) { duke@435: _flags |= _has_localvariable_table; duke@435: *(localvariable_table_length_addr()) = localvariable_table_len; duke@435: } duke@435: } duke@435: duke@435: duke@435: int constMethodOopDesc::checked_exceptions_length() const { duke@435: return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0; duke@435: } duke@435: duke@435: duke@435: CheckedExceptionElement* constMethodOopDesc::checked_exceptions_start() const { duke@435: u2* addr = checked_exceptions_length_addr(); duke@435: u2 length = *addr; duke@435: assert(length > 0, "should only be called if table is present"); duke@435: addr -= length * sizeof(CheckedExceptionElement) / sizeof(u2); duke@435: return (CheckedExceptionElement*) addr; duke@435: } duke@435: duke@435: duke@435: int constMethodOopDesc::localvariable_table_length() const { duke@435: return has_localvariable_table() ? *(localvariable_table_length_addr()) : 0; duke@435: } duke@435: duke@435: duke@435: LocalVariableTableElement* constMethodOopDesc::localvariable_table_start() const { duke@435: u2* addr = localvariable_table_length_addr(); duke@435: u2 length = *addr; duke@435: assert(length > 0, "should only be called if table is present"); duke@435: addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2); duke@435: return (LocalVariableTableElement*) addr; duke@435: }