src/share/vm/oops/constMethod.hpp

Mon, 14 Jan 2013 11:01:39 -0500

author
coleenp
date
Mon, 14 Jan 2013 11:01:39 -0500
changeset 4431
f9eb431c3efe
parent 4398
ade95d680b42
child 4497
16fb9f942703
permissions
-rw-r--r--

8006005: Fix constant pool index validation and alignment trap for method parameter reflection
Summary: This patch addresses an alignment trap due to the storage format of method parameters data in constMethod. It also adds code to validate constant pool indexes for method parameters data.
Reviewed-by: jrose, dholmes
Contributed-by: eric.mccorkle@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 #ifndef SHARE_VM_OOPS_CONSTMETHODOOP_HPP
    26 #define SHARE_VM_OOPS_CONSTMETHODOOP_HPP
    28 #include "oops/oop.hpp"
    30 // An ConstMethod* represents portions of a Java method which
    31 // do not vary.
    32 //
    33 // Memory layout (each line represents a word). Note that most
    34 // applications load thousands of methods, so keeping the size of this
    35 // structure small has a big impact on footprint.
    36 //
    37 // |------------------------------------------------------|
    38 // | header                                               |
    39 // | klass                                                |
    40 // |------------------------------------------------------|
    41 // | fingerprint 1                                        |
    42 // | fingerprint 2                                        |
    43 // | constants                      (oop)                 |
    44 // | stackmap_data                  (oop)                 |
    45 // | constMethod_size                                     |
    46 // | interp_kind  | flags    | code_size                  |
    47 // | name index              | signature index            |
    48 // | method_idnum            | max_stack                  |
    49 // | max_locals              | size_of_parameters         |
    50 // |------------------------------------------------------|
    51 // |                                                      |
    52 // | byte codes                                           |
    53 // |                                                      |
    54 // |------------------------------------------------------|
    55 // | compressed linenumber table                          |
    56 // |  (see class CompressedLineNumberReadStream)          |
    57 // |  (note that length is unknown until decompressed)    |
    58 // |  (access flags bit tells whether table is present)   |
    59 // |  (indexed from start of ConstMethod*)                |
    60 // |  (elements not necessarily sorted!)                  |
    61 // |------------------------------------------------------|
    62 // | localvariable table elements + length (length last)  |
    63 // |  (length is u2, elements are 6-tuples of u2)         |
    64 // |  (see class LocalVariableTableElement)               |
    65 // |  (access flags bit tells whether table is present)   |
    66 // |  (indexed from end of ConstMethod*)                  |
    67 // |------------------------------------------------------|
    68 // | exception table + length (length last)               |
    69 // |  (length is u2, elements are 4-tuples of u2)         |
    70 // |  (see class ExceptionTableElement)                   |
    71 // |  (access flags bit tells whether table is present)   |
    72 // |  (indexed from end of ConstMethod*)                  |
    73 // |------------------------------------------------------|
    74 // | checked exceptions elements + length (length last)   |
    75 // |  (length is u2, elements are u2)                     |
    76 // |  (see class CheckedExceptionElement)                 |
    77 // |  (access flags bit tells whether table is present)   |
    78 // |  (indexed from end of ConstMethod*)                  |
    79 // |------------------------------------------------------|
    80 // | method parameters elements + length (length last)    |
    81 // |  (length is u2, elements are u2, u4 structures)      |
    82 // |  (see class MethodParametersElement)                 |
    83 // |  (access flags bit tells whether table is present)   |
    84 // |  (indexed from end of ConstMethod*)                  |
    85 // |------------------------------------------------------|
    86 // | generic signature index (u2)                         |
    87 // |  (indexed from start of constMethodOop)              |
    88 // |------------------------------------------------------|
    89 //
    90 // IMPORTANT: If anything gets added here, there need to be changes to
    91 // ensure that ServicabilityAgent doesn't get broken as a result!
    94 // Utitily class decribing elements in checked exceptions table inlined in Method*.
    95 class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
    96  public:
    97   u2 class_cp_index;
    98 };
   101 // Utitily class decribing elements in local variable table inlined in Method*.
   102 class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
   103  public:
   104   u2 start_bci;
   105   u2 length;
   106   u2 name_cp_index;
   107   u2 descriptor_cp_index;
   108   u2 signature_cp_index;
   109   u2 slot;
   110 };
   112 // Utitily class describing elements in exception table
   113 class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
   114  public:
   115   u2 start_pc;
   116   u2 end_pc;
   117   u2 handler_pc;
   118   u2 catch_type_index;
   119 };
   121 // Utility class describing elements in method parameters
   122 class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
   123  public:
   124   u2 name_cp_index;
   125   // This has to happen, otherwise it will cause SIGBUS from a
   126   // misaligned u4 on some architectures (ie SPARC)
   127   // because MethodParametersElements are only aligned mod 2
   128   // within the ConstMethod container  u2 flags_hi;
   129   u2 flags_hi;
   130   u2 flags_lo;
   131 };
   134 class ConstMethod : public MetaspaceObj {
   135   friend class VMStructs;
   137 public:
   138   typedef enum { NORMAL, OVERPASS } MethodType;
   140 private:
   141   enum {
   142     _has_linenumber_table = 1,
   143     _has_checked_exceptions = 2,
   144     _has_localvariable_table = 4,
   145     _has_exception_table = 8,
   146     _has_generic_signature = 16,
   147     _has_method_parameters = 32,
   148     _is_overpass = 64
   149   };
   151   // Bit vector of signature
   152   // Callers interpret 0=not initialized yet and
   153   // -1=too many args to fix, must parse the slow way.
   154   // The real initial value is special to account for nonatomicity of 64 bit
   155   // loads and stores.  This value may updated and read without a lock by
   156   // multiple threads, so is volatile.
   157   volatile uint64_t _fingerprint;
   159   ConstantPool*     _constants;                  // Constant pool
   161   // Raw stackmap data for the method
   162   Array<u1>*        _stackmap_data;
   164   int               _constMethod_size;
   165   jbyte             _interpreter_kind;
   166   jbyte             _flags;
   168   // Size of Java bytecodes allocated immediately after Method*.
   169   u2                _code_size;
   170   u2                _name_index;                 // Method name (index in constant pool)
   171   u2                _signature_index;            // Method signature (index in constant pool)
   172   u2                _method_idnum;               // unique identification number for the method within the class
   173                                                  // initially corresponds to the index into the methods array.
   174                                                  // but this may change with redefinition
   175   u2                _max_stack;                  // Maximum number of entries on the expression stack
   176   u2                _max_locals;                 // Number of local variables used by this method
   177   u2                _size_of_parameters;         // size of the parameter block (receiver + arguments) in words
   179   // Constructor
   180   ConstMethod(int byte_code_size,
   181               int compressed_line_number_size,
   182               int localvariable_table_length,
   183               int exception_table_length,
   184               int checked_exceptions_length,
   185               int method_parameters_length,
   186               u2  generic_signature_index,
   187               MethodType is_overpass,
   188               int size);
   189 public:
   191   static ConstMethod* allocate(ClassLoaderData* loader_data,
   192                                int byte_code_size,
   193                                int compressed_line_number_size,
   194                                int localvariable_table_length,
   195                                int exception_table_length,
   196                                int checked_exceptions_length,
   197                                int method_parameters_length,
   198                                u2  generic_signature_index,
   199                                MethodType mt,
   200                                TRAPS);
   202   bool is_constMethod() const { return true; }
   204   // Inlined tables
   205   void set_inlined_tables_length(u2  generic_signature_index,
   206                                  int checked_exceptions_len,
   207                                  int compressed_line_number_size,
   208                                  int localvariable_table_len,
   209                                  int exception_table_len,
   210                                  int method_parameters_length);
   212   bool has_generic_signature() const
   213     { return (_flags & _has_generic_signature) != 0; }
   215   bool has_linenumber_table() const
   216     { return (_flags & _has_linenumber_table) != 0; }
   218   bool has_checked_exceptions() const
   219     { return (_flags & _has_checked_exceptions) != 0; }
   221   bool has_localvariable_table() const
   222     { return (_flags & _has_localvariable_table) != 0; }
   224   bool has_exception_handler() const
   225     { return (_flags & _has_exception_table) != 0; }
   227   bool has_method_parameters() const
   228     { return (_flags & _has_method_parameters) != 0; }
   230   MethodType method_type() const {
   231     return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
   232   }
   234   void set_method_type(MethodType mt) {
   235     if (mt == NORMAL) {
   236       _flags &= ~(_is_overpass);
   237     } else {
   238       _flags |= _is_overpass;
   239     }
   240   }
   243   void set_interpreter_kind(int kind)      { _interpreter_kind = kind; }
   244   int  interpreter_kind(void) const        { return _interpreter_kind; }
   246   // constant pool
   247   ConstantPool* constants() const        { return _constants; }
   248   void set_constants(ConstantPool* c)    { _constants = c; }
   250   Method* method() const;
   252   // stackmap table data
   253   Array<u1>* stackmap_data() const { return _stackmap_data; }
   254   void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }
   255   bool has_stackmap_table() const { return _stackmap_data != NULL; }
   257   void init_fingerprint() {
   258     const uint64_t initval = CONST64(0x8000000000000000);
   259     _fingerprint = initval;
   260   }
   262   uint64_t fingerprint() const                   {
   263     // Since reads aren't atomic for 64 bits, if any of the high or low order
   264     // word is the initial value, return 0.  See init_fingerprint for initval.
   265     uint high_fp = (uint)(_fingerprint >> 32);
   266     if ((int) _fingerprint == 0 || high_fp == 0x80000000) {
   267       return 0L;
   268     } else {
   269       return _fingerprint;
   270     }
   271   }
   273   uint64_t set_fingerprint(uint64_t new_fingerprint) {
   274 #ifdef ASSERT
   275     // Assert only valid if complete/valid 64 bit _fingerprint value is read.
   276     uint64_t oldfp = fingerprint();
   277 #endif // ASSERT
   278     _fingerprint = new_fingerprint;
   279     assert(oldfp == 0L || new_fingerprint == oldfp,
   280            "fingerprint cannot change");
   281     assert(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0,
   282            "fingerprint should call init to set initial value");
   283     return new_fingerprint;
   284   }
   286   // name
   287   int name_index() const                         { return _name_index; }
   288   void set_name_index(int index)                 { _name_index = index; }
   290   // signature
   291   int signature_index() const                    { return _signature_index; }
   292   void set_signature_index(int index)            { _signature_index = index; }
   294   // generics support
   295   int generic_signature_index() const            {
   296     if (has_generic_signature()) {
   297       return *generic_signature_index_addr();
   298     } else {
   299       return 0;
   300     }
   301   }
   302   void set_generic_signature_index(u2 index)    {
   303     assert(has_generic_signature(), "");
   304     u2* addr = generic_signature_index_addr();
   305     *addr = index;
   306   }
   308   // Sizing
   309   static int header_size() {
   310     return sizeof(ConstMethod)/HeapWordSize;
   311   }
   313   // Size needed
   314   static int size(int code_size, int compressed_line_number_size,
   315                   int local_variable_table_length,
   316                   int exception_table_length,
   317                   int checked_exceptions_length,
   318                   int method_parameters_length,
   319                   u2  generic_signature_index);
   321   int size() const                    { return _constMethod_size;}
   322   void set_constMethod_size(int size)     { _constMethod_size = size; }
   324   // code size
   325   int code_size() const                          { return _code_size; }
   326   void set_code_size(int size) {
   327     assert(max_method_code_size < (1 << 16),
   328            "u2 is too small to hold method code size in general");
   329     assert(0 <= size && size <= max_method_code_size, "invalid code size");
   330     _code_size = size;
   331   }
   333   // linenumber table - note that length is unknown until decompression,
   334   // see class CompressedLineNumberReadStream.
   335   u_char* compressed_linenumber_table() const;         // not preserved by gc
   336   u2* generic_signature_index_addr() const;
   337   u2* checked_exceptions_length_addr() const;
   338   u2* localvariable_table_length_addr() const;
   339   u2* exception_table_length_addr() const;
   340   u2* method_parameters_length_addr() const;
   342   // checked exceptions
   343   int checked_exceptions_length() const;
   344   CheckedExceptionElement* checked_exceptions_start() const;
   346   // localvariable table
   347   int localvariable_table_length() const;
   348   LocalVariableTableElement* localvariable_table_start() const;
   350   // exception table
   351   int exception_table_length() const;
   352   ExceptionTableElement* exception_table_start() const;
   354   // method parameters table
   355   int method_parameters_length() const;
   356   MethodParametersElement* method_parameters_start() const;
   358   // byte codes
   359   void    set_code(address code) {
   360     if (code_size() > 0) {
   361       memcpy(code_base(), code, code_size());
   362     }
   363   }
   364   address code_base() const            { return (address) (this+1); }
   365   address code_end() const             { return code_base() + code_size(); }
   366   bool    contains(address bcp) const  { return code_base() <= bcp
   367                                                      && bcp < code_end(); }
   368   // Offset to bytecodes
   369   static ByteSize codes_offset()
   370                             { return in_ByteSize(sizeof(ConstMethod)); }
   372   static ByteSize constants_offset()
   373                             { return byte_offset_of(ConstMethod, _constants); }
   375   static ByteSize max_stack_offset()
   376                             { return byte_offset_of(ConstMethod, _max_stack); }
   377   static ByteSize size_of_locals_offset()
   378                             { return byte_offset_of(ConstMethod, _max_locals); }
   379   static ByteSize size_of_parameters_offset()
   380                             { return byte_offset_of(ConstMethod, _size_of_parameters); }
   383   // Unique id for the method
   384   static const u2 MAX_IDNUM;
   385   static const u2 UNSET_IDNUM;
   386   u2 method_idnum() const                        { return _method_idnum; }
   387   void set_method_idnum(u2 idnum)                { _method_idnum = idnum; }
   389   // max stack
   390   int  max_stack() const                         { return _max_stack; }
   391   void set_max_stack(int size)                   { _max_stack = size; }
   393   // max locals
   394   int  max_locals() const                        { return _max_locals; }
   395   void set_max_locals(int size)                  { _max_locals = size; }
   397   // size of parameters
   398   int  size_of_parameters() const                { return _size_of_parameters; }
   399   void set_size_of_parameters(int size)          { _size_of_parameters = size; }
   401   // Deallocation for RedefineClasses
   402   void deallocate_contents(ClassLoaderData* loader_data);
   403   bool is_klass() const { return false; }
   404   DEBUG_ONLY(bool on_stack() { return false; })
   406 private:
   407   // Since the size of the compressed line number table is unknown, the
   408   // offsets of the other variable sized sections are computed backwards
   409   // from the end of the ConstMethod*.
   411   // First byte after ConstMethod*
   412   address constMethod_end() const
   413                           { return (address)((oop*)this + _constMethod_size); }
   415   // Last short in ConstMethod*
   416   u2* last_u2_element() const
   417                                          { return (u2*)constMethod_end() - 1; }
   419  public:
   420   // Printing
   421   void print_on      (outputStream* st) const;
   422   void print_value_on(outputStream* st) const;
   424   const char* internal_name() const { return "{constMethod}"; }
   426   // Verify
   427   void verify_on(outputStream* st);
   428 };
   430 #endif // SHARE_VM_OOPS_CONSTMETHODOOP_HPP

mercurial