src/share/vm/oops/constMethod.cpp

Sat, 01 Sep 2012 13:25:18 -0400

author
coleenp
date
Sat, 01 Sep 2012 13:25:18 -0400
changeset 4037
da91efe96a93
parent 3917
src/share/vm/oops/constMethodOop.cpp@8150fa46d2ed
child 4245
4735d2c84362
permissions
-rw-r--r--

6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>

     1 /*
     2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "interpreter/interpreter.hpp"
    27 #include "memory/gcLocker.hpp"
    28 #include "memory/metadataFactory.hpp"
    29 #include "oops/constMethod.hpp"
    30 #include "oops/method.hpp"
    32 // Static initialization
    33 const u2 ConstMethod::MAX_IDNUM   = 0xFFFE;
    34 const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
    36 ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
    37                                             int byte_code_size,
    38                                             int compressed_line_number_size,
    39                                             int localvariable_table_length,
    40                                             int exception_table_length,
    41                                             int checked_exceptions_length,
    42                                             TRAPS) {
    43   int size = ConstMethod::size(byte_code_size,
    44                                       compressed_line_number_size,
    45                                       localvariable_table_length,
    46                                       exception_table_length,
    47                                       checked_exceptions_length);
    48   return new (loader_data, size, true, THREAD) ConstMethod(
    49                        byte_code_size, compressed_line_number_size,
    50                        localvariable_table_length, exception_table_length,
    51                        checked_exceptions_length, size);
    52 }
    54 ConstMethod::ConstMethod(int byte_code_size,
    55                                        int compressed_line_number_size,
    56                                        int localvariable_table_length,
    57                                        int exception_table_length,
    58                                        int checked_exceptions_length,
    59                                        int size) {
    61   No_Safepoint_Verifier no_safepoint;
    62   set_interpreter_kind(Interpreter::invalid);
    63   init_fingerprint();
    64   set_constants(NULL);
    65   set_stackmap_data(NULL);
    66   set_code_size(byte_code_size);
    67   set_constMethod_size(size);
    68   set_inlined_tables_length(checked_exceptions_length,
    69                             compressed_line_number_size,
    70                             localvariable_table_length,
    71                             exception_table_length);
    72   assert(this->size() == size, "wrong size for object");
    73 }
    76 // Deallocate metadata fields associated with ConstMethod*
    77 void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
    78   set_interpreter_kind(Interpreter::invalid);
    79   if (stackmap_data() != NULL) {
    80     MetadataFactory::free_array<u1>(loader_data, stackmap_data());
    81   }
    82   set_stackmap_data(NULL);
    83 }
    85 // How big must this constMethodObject be?
    87 int ConstMethod::size(int code_size,
    88                                     int compressed_line_number_size,
    89                                     int local_variable_table_length,
    90                                     int exception_table_length,
    91                                     int checked_exceptions_length) {
    92   int extra_bytes = code_size;
    93   if (compressed_line_number_size > 0) {
    94     extra_bytes += compressed_line_number_size;
    95   }
    96   if (checked_exceptions_length > 0) {
    97     extra_bytes += sizeof(u2);
    98     extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement);
    99   }
   100   if (local_variable_table_length > 0) {
   101     extra_bytes += sizeof(u2);
   102     extra_bytes +=
   103               local_variable_table_length * sizeof(LocalVariableTableElement);
   104   }
   105   if (exception_table_length > 0) {
   106     extra_bytes += sizeof(u2);
   107     extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
   108   }
   109   int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
   110   return align_object_size(header_size() + extra_words);
   111 }
   113 Method* ConstMethod::method() const {
   114     return InstanceKlass::cast(_constants->pool_holder())->method_with_idnum(
   115                                _method_idnum);
   116   }
   118 // linenumber table - note that length is unknown until decompression,
   119 // see class CompressedLineNumberReadStream.
   121 u_char* ConstMethod::compressed_linenumber_table() const {
   122   // Located immediately following the bytecodes.
   123   assert(has_linenumber_table(), "called only if table is present");
   124   return code_end();
   125 }
   127 u2* ConstMethod::checked_exceptions_length_addr() const {
   128   // Located at the end of the constMethod.
   129   assert(has_checked_exceptions(), "called only if table is present");
   130   return last_u2_element();
   131 }
   133 u2* ConstMethod::exception_table_length_addr() const {
   134   assert(has_exception_handler(), "called only if table is present");
   135   if (has_checked_exceptions()) {
   136     // If checked_exception present, locate immediately before them.
   137     return (u2*) checked_exceptions_start() - 1;
   138   } else {
   139     // Else, the exception table is at the end of the constMethod.
   140     return last_u2_element();
   141   }
   142 }
   144 u2* ConstMethod::localvariable_table_length_addr() const {
   145   assert(has_localvariable_table(), "called only if table is present");
   146   if (has_exception_handler()) {
   147     // If exception_table present, locate immediately before them.
   148     return (u2*) exception_table_start() - 1;
   149   } else {
   150     if (has_checked_exceptions()) {
   151       // If checked_exception present, locate immediately before them.
   152       return (u2*) checked_exceptions_start() - 1;
   153     } else {
   154       // Else, the linenumber table is at the end of the constMethod.
   155       return last_u2_element();
   156     }
   157   }
   158 }
   161 // Update the flags to indicate the presence of these optional fields.
   162 void ConstMethod::set_inlined_tables_length(
   163                                               int checked_exceptions_len,
   164                                               int compressed_line_number_size,
   165                                               int localvariable_table_len,
   166                                               int exception_table_len) {
   167   // Must be done in the order below, otherwise length_addr accessors
   168   // will not work. Only set bit in header if length is positive.
   169   assert(_flags == 0, "Error");
   170   if (compressed_line_number_size > 0) {
   171     _flags |= _has_linenumber_table;
   172   }
   173   if (checked_exceptions_len > 0) {
   174     _flags |= _has_checked_exceptions;
   175     *(checked_exceptions_length_addr()) = checked_exceptions_len;
   176   }
   177   if (exception_table_len > 0) {
   178     _flags |= _has_exception_table;
   179     *(exception_table_length_addr()) = exception_table_len;
   180   }
   181   if (localvariable_table_len > 0) {
   182     _flags |= _has_localvariable_table;
   183     *(localvariable_table_length_addr()) = localvariable_table_len;
   184   }
   185 }
   188 int ConstMethod::checked_exceptions_length() const {
   189   return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0;
   190 }
   193 CheckedExceptionElement* ConstMethod::checked_exceptions_start() const {
   194   u2* addr = checked_exceptions_length_addr();
   195   u2 length = *addr;
   196   assert(length > 0, "should only be called if table is present");
   197   addr -= length * sizeof(CheckedExceptionElement) / sizeof(u2);
   198   return (CheckedExceptionElement*) addr;
   199 }
   202 int ConstMethod::localvariable_table_length() const {
   203   return has_localvariable_table() ? *(localvariable_table_length_addr()) : 0;
   204 }
   207 LocalVariableTableElement* ConstMethod::localvariable_table_start() const {
   208   u2* addr = localvariable_table_length_addr();
   209   u2 length = *addr;
   210   assert(length > 0, "should only be called if table is present");
   211   addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);
   212   return (LocalVariableTableElement*) addr;
   213 }
   215 int ConstMethod::exception_table_length() const {
   216   return has_exception_handler() ? *(exception_table_length_addr()) : 0;
   217 }
   219 ExceptionTableElement* ConstMethod::exception_table_start() const {
   220   u2* addr = exception_table_length_addr();
   221   u2 length = *addr;
   222   assert(length > 0, "should only be called if table is present");
   223   addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);
   224   return (ExceptionTableElement*)addr;
   225 }
   228 // Printing
   230 void ConstMethod::print_on(outputStream* st) const {
   231   ResourceMark rm;
   232   assert(is_constMethod(), "must be constMethod");
   233   st->print_cr(internal_name());
   234   st->print(" - method:       " INTPTR_FORMAT " ", (address)method());
   235   method()->print_value_on(st); st->cr();
   236   if (has_stackmap_table()) {
   237     st->print(" - stackmap data:       ");
   238     stackmap_data()->print_value_on(st);
   239     st->cr();
   240   }
   241 }
   243 // Short version of printing ConstMethod* - just print the name of the
   244 // method it belongs to.
   245 void ConstMethod::print_value_on(outputStream* st) const {
   246   assert(is_constMethod(), "must be constMethod");
   247   st->print(" const part of method " );
   248   method()->print_value_on(st);
   249 }
   252 // Verification
   254 void ConstMethod::verify_on(outputStream* st) {
   255   guarantee(is_constMethod(), "object must be constMethod");
   256   guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this));
   258   // Verification can occur during oop construction before the method or
   259   // other fields have been initialized.
   260   guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this));
   261   guarantee(method()->is_method(), "should be method");
   263   address m_end = (address)((oop*) this + size());
   264   address compressed_table_start = code_end();
   265   guarantee(compressed_table_start <= m_end, "invalid method layout");
   266   address compressed_table_end = compressed_table_start;
   267   // Verify line number table
   268   if (has_linenumber_table()) {
   269     CompressedLineNumberReadStream stream(compressed_linenumber_table());
   270     while (stream.read_pair()) {
   271       guarantee(stream.bci() >= 0 && stream.bci() <= code_size(), "invalid bci in line number table");
   272     }
   273     compressed_table_end += stream.position();
   274   }
   275   guarantee(compressed_table_end <= m_end, "invalid method layout");
   276   // Verify checked exceptions, exception table and local variable tables
   277   if (has_checked_exceptions()) {
   278     u2* addr = checked_exceptions_length_addr();
   279     guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
   280   }
   281   if (has_exception_handler()) {
   282     u2* addr = exception_table_length_addr();
   283      guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
   284   }
   285   if (has_localvariable_table()) {
   286     u2* addr = localvariable_table_length_addr();
   287     guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
   288   }
   289   // Check compressed_table_end relative to uncompressed_table_start
   290   u2* uncompressed_table_start;
   291   if (has_localvariable_table()) {
   292     uncompressed_table_start = (u2*) localvariable_table_start();
   293   } else if (has_exception_handler()) {
   294     uncompressed_table_start = (u2*) exception_table_start();
   295   } else if (has_checked_exceptions()) {
   296       uncompressed_table_start = (u2*) checked_exceptions_start();
   297   } else {
   298       uncompressed_table_start = (u2*) m_end;
   299   }
   300   int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;
   301   int max_gap = align_object_size(1)*BytesPerWord;
   302   guarantee(gap >= 0 && gap < max_gap, "invalid method layout");
   303 }

mercurial