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

duke@435 1 /*
jiangli@3826 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #ifndef SHARE_VM_OOPS_CONSTMETHODOOP_HPP
stefank@2314 26 #define SHARE_VM_OOPS_CONSTMETHODOOP_HPP
stefank@2314 27
stefank@2314 28 #include "oops/oop.hpp"
stefank@2314 29
coleenp@4037 30 // An ConstMethod* represents portions of a Java method which
duke@435 31 // do not vary.
duke@435 32 //
duke@435 33 // Memory layout (each line represents a word). Note that most
duke@435 34 // applications load thousands of methods, so keeping the size of this
duke@435 35 // structure small has a big impact on footprint.
duke@435 36 //
duke@435 37 // |------------------------------------------------------|
duke@435 38 // | header |
duke@435 39 // | klass |
duke@435 40 // |------------------------------------------------------|
duke@435 41 // | fingerprint 1 |
duke@435 42 // | fingerprint 2 |
jiangli@3826 43 // | constants (oop) |
duke@435 44 // | stackmap_data (oop) |
duke@435 45 // | constMethod_size |
duke@435 46 // | interp_kind | flags | code_size |
duke@435 47 // | name index | signature index |
jiangli@4302 48 // | method_idnum | max_stack |
jiangli@4338 49 // | max_locals | size_of_parameters |
duke@435 50 // |------------------------------------------------------|
duke@435 51 // | |
duke@435 52 // | byte codes |
duke@435 53 // | |
duke@435 54 // |------------------------------------------------------|
duke@435 55 // | compressed linenumber table |
duke@435 56 // | (see class CompressedLineNumberReadStream) |
duke@435 57 // | (note that length is unknown until decompressed) |
duke@435 58 // | (access flags bit tells whether table is present) |
jiangli@4302 59 // | (indexed from start of ConstMethod*) |
duke@435 60 // | (elements not necessarily sorted!) |
duke@435 61 // |------------------------------------------------------|
duke@435 62 // | localvariable table elements + length (length last) |
duke@435 63 // | (length is u2, elements are 6-tuples of u2) |
duke@435 64 // | (see class LocalVariableTableElement) |
duke@435 65 // | (access flags bit tells whether table is present) |
jiangli@4302 66 // | (indexed from end of ConstMethod*) |
jiangli@3917 67 // |------------------------------------------------------|
jiangli@3917 68 // | exception table + length (length last) |
jiangli@3917 69 // | (length is u2, elements are 4-tuples of u2) |
jiangli@3917 70 // | (see class ExceptionTableElement) |
jiangli@3917 71 // | (access flags bit tells whether table is present) |
jiangli@4302 72 // | (indexed from end of ConstMethod*) |
duke@435 73 // |------------------------------------------------------|
duke@435 74 // | checked exceptions elements + length (length last) |
duke@435 75 // | (length is u2, elements are u2) |
duke@435 76 // | (see class CheckedExceptionElement) |
duke@435 77 // | (access flags bit tells whether table is present) |
jiangli@4302 78 // | (indexed from end of ConstMethod*) |
jiangli@4302 79 // |------------------------------------------------------|
coleenp@4398 80 // | method parameters elements + length (length last) |
coleenp@4398 81 // | (length is u2, elements are u2, u4 structures) |
coleenp@4398 82 // | (see class MethodParametersElement) |
coleenp@4398 83 // | (access flags bit tells whether table is present) |
coleenp@4398 84 // | (indexed from end of ConstMethod*) |
coleenp@4398 85 // |------------------------------------------------------|
jiangli@4302 86 // | generic signature index (u2) |
jiangli@4302 87 // | (indexed from start of constMethodOop) |
duke@435 88 // |------------------------------------------------------|
coleenp@4398 89 //
coleenp@4398 90 // IMPORTANT: If anything gets added here, there need to be changes to
coleenp@4398 91 // ensure that ServicabilityAgent doesn't get broken as a result!
duke@435 92
duke@435 93
coleenp@4037 94 // Utitily class decribing elements in checked exceptions table inlined in Method*.
duke@435 95 class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
duke@435 96 public:
duke@435 97 u2 class_cp_index;
duke@435 98 };
duke@435 99
duke@435 100
coleenp@4037 101 // Utitily class decribing elements in local variable table inlined in Method*.
duke@435 102 class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
duke@435 103 public:
duke@435 104 u2 start_bci;
duke@435 105 u2 length;
duke@435 106 u2 name_cp_index;
duke@435 107 u2 descriptor_cp_index;
duke@435 108 u2 signature_cp_index;
duke@435 109 u2 slot;
duke@435 110 };
duke@435 111
jiangli@3917 112 // Utitily class describing elements in exception table
jiangli@3917 113 class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
jiangli@3917 114 public:
jiangli@3917 115 u2 start_pc;
jiangli@3917 116 u2 end_pc;
jiangli@3917 117 u2 handler_pc;
jiangli@3917 118 u2 catch_type_index;
jiangli@3917 119 };
jiangli@3917 120
coleenp@4398 121 // Utility class describing elements in method parameters
coleenp@4398 122 class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
coleenp@4398 123 public:
coleenp@4398 124 u2 name_cp_index;
coleenp@4431 125 // This has to happen, otherwise it will cause SIGBUS from a
coleenp@4431 126 // misaligned u4 on some architectures (ie SPARC)
coleenp@4431 127 // because MethodParametersElements are only aligned mod 2
coleenp@4431 128 // within the ConstMethod container u2 flags_hi;
coleenp@4431 129 u2 flags_hi;
coleenp@4431 130 u2 flags_lo;
coleenp@4398 131 };
coleenp@4398 132
coleenp@4037 133
coleenp@4037 134 class ConstMethod : public MetaspaceObj {
duke@435 135 friend class VMStructs;
kamg@4245 136
kamg@4245 137 public:
kamg@4245 138 typedef enum { NORMAL, OVERPASS } MethodType;
kamg@4245 139
duke@435 140 private:
duke@435 141 enum {
duke@435 142 _has_linenumber_table = 1,
duke@435 143 _has_checked_exceptions = 2,
jiangli@3917 144 _has_localvariable_table = 4,
kamg@4245 145 _has_exception_table = 8,
jiangli@4302 146 _has_generic_signature = 16,
coleenp@4398 147 _has_method_parameters = 32,
coleenp@4398 148 _is_overpass = 64
duke@435 149 };
duke@435 150
duke@435 151 // Bit vector of signature
duke@435 152 // Callers interpret 0=not initialized yet and
duke@435 153 // -1=too many args to fix, must parse the slow way.
duke@435 154 // The real initial value is special to account for nonatomicity of 64 bit
duke@435 155 // loads and stores. This value may updated and read without a lock by
duke@435 156 // multiple threads, so is volatile.
duke@435 157 volatile uint64_t _fingerprint;
duke@435 158
coleenp@4037 159 ConstantPool* _constants; // Constant pool
duke@435 160
duke@435 161 // Raw stackmap data for the method
coleenp@4037 162 Array<u1>* _stackmap_data;
duke@435 163
duke@435 164 int _constMethod_size;
duke@435 165 jbyte _interpreter_kind;
duke@435 166 jbyte _flags;
duke@435 167
coleenp@4037 168 // Size of Java bytecodes allocated immediately after Method*.
duke@435 169 u2 _code_size;
duke@435 170 u2 _name_index; // Method name (index in constant pool)
duke@435 171 u2 _signature_index; // Method signature (index in constant pool)
duke@435 172 u2 _method_idnum; // unique identification number for the method within the class
duke@435 173 // initially corresponds to the index into the methods array.
duke@435 174 // but this may change with redefinition
jiangli@4302 175 u2 _max_stack; // Maximum number of entries on the expression stack
jiangli@4338 176 u2 _max_locals; // Number of local variables used by this method
jiangli@4338 177 u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
coleenp@4037 178
coleenp@4037 179 // Constructor
coleenp@4037 180 ConstMethod(int byte_code_size,
kamg@4245 181 int compressed_line_number_size,
kamg@4245 182 int localvariable_table_length,
kamg@4245 183 int exception_table_length,
kamg@4245 184 int checked_exceptions_length,
coleenp@4398 185 int method_parameters_length,
jiangli@4302 186 u2 generic_signature_index,
kamg@4245 187 MethodType is_overpass,
kamg@4245 188 int size);
duke@435 189 public:
kamg@4245 190
coleenp@4037 191 static ConstMethod* allocate(ClassLoaderData* loader_data,
kamg@4245 192 int byte_code_size,
kamg@4245 193 int compressed_line_number_size,
kamg@4245 194 int localvariable_table_length,
kamg@4245 195 int exception_table_length,
kamg@4245 196 int checked_exceptions_length,
coleenp@4398 197 int method_parameters_length,
jiangli@4302 198 u2 generic_signature_index,
kamg@4245 199 MethodType mt,
kamg@4245 200 TRAPS);
coleenp@4037 201
coleenp@4037 202 bool is_constMethod() const { return true; }
coleenp@4037 203
duke@435 204 // Inlined tables
jiangli@4302 205 void set_inlined_tables_length(u2 generic_signature_index,
jiangli@4302 206 int checked_exceptions_len,
duke@435 207 int compressed_line_number_size,
jiangli@3917 208 int localvariable_table_len,
coleenp@4398 209 int exception_table_len,
coleenp@4398 210 int method_parameters_length);
duke@435 211
jiangli@4302 212 bool has_generic_signature() const
jiangli@4302 213 { return (_flags & _has_generic_signature) != 0; }
jiangli@4302 214
duke@435 215 bool has_linenumber_table() const
duke@435 216 { return (_flags & _has_linenumber_table) != 0; }
duke@435 217
duke@435 218 bool has_checked_exceptions() const
duke@435 219 { return (_flags & _has_checked_exceptions) != 0; }
duke@435 220
duke@435 221 bool has_localvariable_table() const
duke@435 222 { return (_flags & _has_localvariable_table) != 0; }
duke@435 223
jiangli@3917 224 bool has_exception_handler() const
jiangli@3917 225 { return (_flags & _has_exception_table) != 0; }
jiangli@3917 226
coleenp@4398 227 bool has_method_parameters() const
coleenp@4398 228 { return (_flags & _has_method_parameters) != 0; }
coleenp@4398 229
kamg@4245 230 MethodType method_type() const {
kamg@4245 231 return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
kamg@4245 232 }
kamg@4245 233
kamg@4245 234 void set_method_type(MethodType mt) {
kamg@4245 235 if (mt == NORMAL) {
kamg@4245 236 _flags &= ~(_is_overpass);
kamg@4245 237 } else {
kamg@4245 238 _flags |= _is_overpass;
kamg@4245 239 }
kamg@4245 240 }
kamg@4245 241
kamg@4245 242
duke@435 243 void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
duke@435 244 int interpreter_kind(void) const { return _interpreter_kind; }
duke@435 245
jiangli@3826 246 // constant pool
coleenp@4037 247 ConstantPool* constants() const { return _constants; }
coleenp@4037 248 void set_constants(ConstantPool* c) { _constants = c; }
duke@435 249
coleenp@4037 250 Method* method() const;
duke@435 251
duke@435 252 // stackmap table data
coleenp@4037 253 Array<u1>* stackmap_data() const { return _stackmap_data; }
coleenp@4037 254 void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }
duke@435 255 bool has_stackmap_table() const { return _stackmap_data != NULL; }
duke@435 256
duke@435 257 void init_fingerprint() {
duke@435 258 const uint64_t initval = CONST64(0x8000000000000000);
duke@435 259 _fingerprint = initval;
duke@435 260 }
duke@435 261
duke@435 262 uint64_t fingerprint() const {
duke@435 263 // Since reads aren't atomic for 64 bits, if any of the high or low order
duke@435 264 // word is the initial value, return 0. See init_fingerprint for initval.
duke@435 265 uint high_fp = (uint)(_fingerprint >> 32);
duke@435 266 if ((int) _fingerprint == 0 || high_fp == 0x80000000) {
duke@435 267 return 0L;
duke@435 268 } else {
duke@435 269 return _fingerprint;
duke@435 270 }
duke@435 271 }
duke@435 272
duke@435 273 uint64_t set_fingerprint(uint64_t new_fingerprint) {
duke@435 274 #ifdef ASSERT
duke@435 275 // Assert only valid if complete/valid 64 bit _fingerprint value is read.
duke@435 276 uint64_t oldfp = fingerprint();
duke@435 277 #endif // ASSERT
duke@435 278 _fingerprint = new_fingerprint;
duke@435 279 assert(oldfp == 0L || new_fingerprint == oldfp,
duke@435 280 "fingerprint cannot change");
duke@435 281 assert(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0,
duke@435 282 "fingerprint should call init to set initial value");
duke@435 283 return new_fingerprint;
duke@435 284 }
duke@435 285
duke@435 286 // name
duke@435 287 int name_index() const { return _name_index; }
duke@435 288 void set_name_index(int index) { _name_index = index; }
duke@435 289
duke@435 290 // signature
duke@435 291 int signature_index() const { return _signature_index; }
duke@435 292 void set_signature_index(int index) { _signature_index = index; }
duke@435 293
duke@435 294 // generics support
jiangli@4302 295 int generic_signature_index() const {
jiangli@4302 296 if (has_generic_signature()) {
jiangli@4302 297 return *generic_signature_index_addr();
jiangli@4302 298 } else {
jiangli@4302 299 return 0;
jiangli@4302 300 }
jiangli@4302 301 }
jiangli@4302 302 void set_generic_signature_index(u2 index) {
jiangli@4302 303 assert(has_generic_signature(), "");
jiangli@4302 304 u2* addr = generic_signature_index_addr();
jiangli@4302 305 *addr = index;
jiangli@4302 306 }
duke@435 307
duke@435 308 // Sizing
duke@435 309 static int header_size() {
coleenp@4037 310 return sizeof(ConstMethod)/HeapWordSize;
duke@435 311 }
duke@435 312
coleenp@4037 313 // Size needed
coleenp@4037 314 static int size(int code_size, int compressed_line_number_size,
coleenp@4398 315 int local_variable_table_length,
coleenp@4398 316 int exception_table_length,
coleenp@4398 317 int checked_exceptions_length,
coleenp@4398 318 int method_parameters_length,
coleenp@4398 319 u2 generic_signature_index);
duke@435 320
coleenp@4037 321 int size() const { return _constMethod_size;}
duke@435 322 void set_constMethod_size(int size) { _constMethod_size = size; }
duke@435 323
duke@435 324 // code size
duke@435 325 int code_size() const { return _code_size; }
duke@435 326 void set_code_size(int size) {
duke@435 327 assert(max_method_code_size < (1 << 16),
duke@435 328 "u2 is too small to hold method code size in general");
duke@435 329 assert(0 <= size && size <= max_method_code_size, "invalid code size");
duke@435 330 _code_size = size;
duke@435 331 }
duke@435 332
duke@435 333 // linenumber table - note that length is unknown until decompression,
duke@435 334 // see class CompressedLineNumberReadStream.
duke@435 335 u_char* compressed_linenumber_table() const; // not preserved by gc
jiangli@4302 336 u2* generic_signature_index_addr() const;
duke@435 337 u2* checked_exceptions_length_addr() const;
duke@435 338 u2* localvariable_table_length_addr() const;
jiangli@3917 339 u2* exception_table_length_addr() const;
coleenp@4398 340 u2* method_parameters_length_addr() const;
duke@435 341
duke@435 342 // checked exceptions
duke@435 343 int checked_exceptions_length() const;
duke@435 344 CheckedExceptionElement* checked_exceptions_start() const;
duke@435 345
duke@435 346 // localvariable table
duke@435 347 int localvariable_table_length() const;
duke@435 348 LocalVariableTableElement* localvariable_table_start() const;
duke@435 349
jiangli@3917 350 // exception table
jiangli@3917 351 int exception_table_length() const;
jiangli@3917 352 ExceptionTableElement* exception_table_start() const;
jiangli@3917 353
coleenp@4398 354 // method parameters table
coleenp@4398 355 int method_parameters_length() const;
coleenp@4398 356 MethodParametersElement* method_parameters_start() const;
coleenp@4398 357
duke@435 358 // byte codes
twisti@1573 359 void set_code(address code) {
twisti@1573 360 if (code_size() > 0) {
twisti@1573 361 memcpy(code_base(), code, code_size());
twisti@1573 362 }
twisti@1573 363 }
duke@435 364 address code_base() const { return (address) (this+1); }
duke@435 365 address code_end() const { return code_base() + code_size(); }
duke@435 366 bool contains(address bcp) const { return code_base() <= bcp
duke@435 367 && bcp < code_end(); }
duke@435 368 // Offset to bytecodes
duke@435 369 static ByteSize codes_offset()
coleenp@4037 370 { return in_ByteSize(sizeof(ConstMethod)); }
duke@435 371
jiangli@3826 372 static ByteSize constants_offset()
coleenp@4037 373 { return byte_offset_of(ConstMethod, _constants); }
duke@435 374
jiangli@4302 375 static ByteSize max_stack_offset()
jiangli@4302 376 { return byte_offset_of(ConstMethod, _max_stack); }
jiangli@4338 377 static ByteSize size_of_locals_offset()
jiangli@4338 378 { return byte_offset_of(ConstMethod, _max_locals); }
jiangli@4338 379 static ByteSize size_of_parameters_offset()
jiangli@4338 380 { return byte_offset_of(ConstMethod, _size_of_parameters); }
jiangli@4338 381
jiangli@4302 382
duke@435 383 // Unique id for the method
duke@435 384 static const u2 MAX_IDNUM;
duke@435 385 static const u2 UNSET_IDNUM;
duke@435 386 u2 method_idnum() const { return _method_idnum; }
duke@435 387 void set_method_idnum(u2 idnum) { _method_idnum = idnum; }
duke@435 388
jiangli@4302 389 // max stack
jiangli@4302 390 int max_stack() const { return _max_stack; }
jiangli@4302 391 void set_max_stack(int size) { _max_stack = size; }
jiangli@4302 392
jiangli@4338 393 // max locals
jiangli@4338 394 int max_locals() const { return _max_locals; }
jiangli@4338 395 void set_max_locals(int size) { _max_locals = size; }
jiangli@4338 396
jiangli@4338 397 // size of parameters
jiangli@4338 398 int size_of_parameters() const { return _size_of_parameters; }
jiangli@4338 399 void set_size_of_parameters(int size) { _size_of_parameters = size; }
jiangli@4338 400
coleenp@4037 401 // Deallocation for RedefineClasses
coleenp@4037 402 void deallocate_contents(ClassLoaderData* loader_data);
coleenp@4037 403 bool is_klass() const { return false; }
coleenp@4037 404 DEBUG_ONLY(bool on_stack() { return false; })
coleenp@4037 405
duke@435 406 private:
duke@435 407 // Since the size of the compressed line number table is unknown, the
duke@435 408 // offsets of the other variable sized sections are computed backwards
coleenp@4037 409 // from the end of the ConstMethod*.
duke@435 410
coleenp@4037 411 // First byte after ConstMethod*
duke@435 412 address constMethod_end() const
duke@435 413 { return (address)((oop*)this + _constMethod_size); }
duke@435 414
coleenp@4037 415 // Last short in ConstMethod*
duke@435 416 u2* last_u2_element() const
duke@435 417 { return (u2*)constMethod_end() - 1; }
coleenp@4037 418
coleenp@4037 419 public:
coleenp@4037 420 // Printing
coleenp@4037 421 void print_on (outputStream* st) const;
coleenp@4037 422 void print_value_on(outputStream* st) const;
coleenp@4037 423
coleenp@4037 424 const char* internal_name() const { return "{constMethod}"; }
coleenp@4037 425
coleenp@4037 426 // Verify
coleenp@4037 427 void verify_on(outputStream* st);
duke@435 428 };
stefank@2314 429
stefank@2314 430 #endif // SHARE_VM_OOPS_CONSTMETHODOOP_HPP

mercurial