diff src/share/vm/classfile/classFileParser.cpp @ 10408:836a62f43af9

Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/
author Doug Simon <doug.simon@oracle.com>
date Wed, 19 Jun 2013 10:45:56 +0200
parents f2aebc22372a f2110083203d
children 6b0fd0964b87
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp	Tue Jun 18 14:23:29 2013 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Wed Jun 19 10:45:56 2013 +0200
@@ -39,6 +39,7 @@
 #include "memory/gcLocker.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
+#include "memory/referenceType.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/constantPool.hpp"
 #include "oops/fieldStreams.hpp"
@@ -436,14 +437,19 @@
               ref_index, CHECK_(nullHandle));
             break;
           case JVM_REF_invokeVirtual:
-          case JVM_REF_invokeStatic:
-          case JVM_REF_invokeSpecial:
           case JVM_REF_newInvokeSpecial:
             check_property(
               tag.is_method(),
               "Invalid constant pool index %u in class file %s (not a method)",
               ref_index, CHECK_(nullHandle));
             break;
+          case JVM_REF_invokeStatic:
+          case JVM_REF_invokeSpecial:
+            check_property(tag.is_method() ||
+                           ((_major_version >= JAVA_8_VERSION) && tag.is_interface_method()),
+               "Invalid constant pool index %u in class file %s (not a method)",
+               ref_index, CHECK_(nullHandle));
+             break;
           case JVM_REF_invokeInterface:
             check_property(
               tag.is_interface_method(),
@@ -1714,15 +1720,28 @@
     coll->set_annotation(id);
 
     if (id == AnnotationCollector::_sun_misc_Contended) {
+      // @Contended can optionally specify the contention group.
+      //
+      // Contended group defines the equivalence class over the fields:
+      // the fields within the same contended group are not treated distinct.
+      // The only exception is default group, which does not incur the
+      // equivalence. Naturally, contention group for classes is meaningless.
+      //
+      // While the contention group is specified as String, annotation
+      // values are already interned, and we might as well use the constant
+      // pool index as the group tag.
+      //
+      u2 group_index = 0; // default contended group
       if (count == 1
           && s_size == (index - index0)  // match size
           && s_tag_val == *(abase + tag_off)
           && member == vmSymbols::value_name()) {
-        u2 group_index = Bytes::get_Java_u2(abase + s_con_off);
-        coll->set_contended_group(group_index);
-      } else {
-        coll->set_contended_group(0); // default contended group
+        group_index = Bytes::get_Java_u2(abase + s_con_off);
+        if (_cp->symbol_at(group_index)->utf8_length() == 0) {
+          group_index = 0; // default contended group
+        }
       }
+      coll->set_contended_group(group_index);
     }
   }
 }
@@ -2022,7 +2041,6 @@
   u2 method_parameters_length = 0;
   u1* method_parameters_data = NULL;
   bool method_parameters_seen = false;
-  bool method_parameters_four_byte_flags;
   bool parsed_code_attribute = false;
   bool parsed_checked_exceptions_attribute = false;
   bool parsed_stackmap_attribute = false;
@@ -2236,26 +2254,14 @@
       }
       method_parameters_seen = true;
       method_parameters_length = cfs->get_u1_fast();
-      // Track the actual size (note: this is written for clarity; a
-      // decent compiler will CSE and constant-fold this into a single
-      // expression)
-      // Use the attribute length to figure out the size of flags
-      if (method_attribute_length == (method_parameters_length * 6u) + 1u) {
-        method_parameters_four_byte_flags = true;
-      } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) {
-        method_parameters_four_byte_flags = false;
-      } else {
+      if (method_attribute_length != (method_parameters_length * 4u) + 1u) {
         classfile_parse_error(
           "Invalid MethodParameters method attribute length %u in class file",
           method_attribute_length, CHECK_(nullHandle));
       }
       method_parameters_data = cfs->get_u1_buffer();
       cfs->skip_u2_fast(method_parameters_length);
-      if (method_parameters_four_byte_flags) {
-        cfs->skip_u4_fast(method_parameters_length);
-      } else {
-        cfs->skip_u2_fast(method_parameters_length);
-      }
+      cfs->skip_u2_fast(method_parameters_length);
       // ignore this attribute if it cannot be reflected
       if (!SystemDictionary::Parameter_klass_loaded())
         method_parameters_length = 0;
@@ -2418,13 +2424,8 @@
     for (int i = 0; i < method_parameters_length; i++) {
       elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data);
       method_parameters_data += 2;
-      if (method_parameters_four_byte_flags) {
-        elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
-        method_parameters_data += 4;
-      } else {
-        elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
-        method_parameters_data += 2;
-      }
+      elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
+      method_parameters_data += 2;
     }
   }
 
@@ -3066,7 +3067,7 @@
     }
   }
 }
-#endif // ASSERT
+#endif // def ASSERT
 
 
 instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index,
@@ -3121,15 +3122,8 @@
                                     FieldLayoutInfo* info,
                                     TRAPS) {
 
-  // get the padding width from the option
-  // TODO: Ask VM about specific CPU we are running on
-  int pad_size = ContendedPaddingWidth;
-
   // Field size and offset computation
   int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size();
-#ifndef PRODUCT
-  int orig_nonstatic_field_size = 0;
-#endif
   int next_static_oop_offset;
   int next_static_double_offset;
   int next_static_word_offset;
@@ -3140,13 +3134,14 @@
   int next_nonstatic_word_offset;
   int next_nonstatic_short_offset;
   int next_nonstatic_byte_offset;
-  int next_nonstatic_type_offset;
   int first_nonstatic_oop_offset;
-  int first_nonstatic_field_offset;
   int next_nonstatic_field_offset;
   int next_nonstatic_padded_offset;
 
   // Count the contended fields by type.
+  //
+  // We ignore static fields, because @Contended is not supported for them.
+  // The layout code below will also ignore the static fields.
   int nonstatic_contended_count = 0;
   FieldAllocationCount fac_contended;
   for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
@@ -3158,7 +3153,6 @@
       }
     }
   }
-  int contended_count = nonstatic_contended_count;
 
 
   // Calculate the starting byte offsets
@@ -3178,61 +3172,60 @@
   next_static_byte_offset     = next_static_short_offset +
                                 ((fac->count[STATIC_SHORT]) * BytesPerShort);
 
-  first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
-                                 nonstatic_field_size * heapOopSize;
-
-  // class is contended, pad before all the fields
-  if (parsed_annotations->is_contended()) {
-    first_nonstatic_field_offset += pad_size;
+  int nonstatic_fields_start  = instanceOopDesc::base_offset_in_bytes() +
+                                nonstatic_field_size * heapOopSize;
+
+  next_nonstatic_field_offset = nonstatic_fields_start;
+
+  bool is_contended_class     = parsed_annotations->is_contended();
+
+  // Class is contended, pad before all the fields
+  if (is_contended_class) {
+    next_nonstatic_field_offset += ContendedPaddingWidth;
   }
 
-  next_nonstatic_field_offset = first_nonstatic_field_offset;
-
+  // Compute the non-contended fields count.
+  // The packing code below relies on these counts to determine if some field
+  // can be squeezed into the alignment gap. Contended fields are obviously
+  // exempt from that.
   unsigned int nonstatic_double_count = fac->count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
   unsigned int nonstatic_word_count   = fac->count[NONSTATIC_WORD]   - fac_contended.count[NONSTATIC_WORD];
   unsigned int nonstatic_short_count  = fac->count[NONSTATIC_SHORT]  - fac_contended.count[NONSTATIC_SHORT];
   unsigned int nonstatic_byte_count   = fac->count[NONSTATIC_BYTE]   - fac_contended.count[NONSTATIC_BYTE];
   unsigned int nonstatic_oop_count    = fac->count[NONSTATIC_OOP]    - fac_contended.count[NONSTATIC_OOP];
 
+  // Total non-static fields count, including every contended field
+  unsigned int nonstatic_fields_count = fac->count[NONSTATIC_DOUBLE] + fac->count[NONSTATIC_WORD] +
+                                        fac->count[NONSTATIC_SHORT] + fac->count[NONSTATIC_BYTE] +
+                                        fac->count[NONSTATIC_OOP];
+
   bool super_has_nonstatic_fields =
           (_super_klass() != NULL && _super_klass->has_nonstatic_fields());
-  bool has_nonstatic_fields = super_has_nonstatic_fields ||
-          ((nonstatic_double_count + nonstatic_word_count +
-            nonstatic_short_count + nonstatic_byte_count +
-            nonstatic_oop_count) != 0);
+  bool has_nonstatic_fields = super_has_nonstatic_fields || (nonstatic_fields_count != 0);
 
 
   // Prepare list of oops for oop map generation.
+  //
+  // "offset" and "count" lists are describing the set of contiguous oop
+  // regions. offset[i] is the start of the i-th region, which then has
+  // count[i] oops following. Before we know how many regions are required,
+  // we pessimistically allocate the maps to fit all the oops into the
+  // distinct regions.
+  //
+  // TODO: We add +1 to always allocate non-zero resource arrays; we need
+  // to figure out if we still need to do this.
   int* nonstatic_oop_offsets;
   unsigned int* nonstatic_oop_counts;
   unsigned int nonstatic_oop_map_count = 0;
+  unsigned int max_nonstatic_oop_maps  = fac->count[NONSTATIC_OOP] + 1;
 
   nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
-            THREAD, int, nonstatic_oop_count + 1);
+            THREAD, int, max_nonstatic_oop_maps);
   nonstatic_oop_counts  = NEW_RESOURCE_ARRAY_IN_THREAD(
-            THREAD, unsigned int, nonstatic_oop_count + 1);
+            THREAD, unsigned int, max_nonstatic_oop_maps);
 
   first_nonstatic_oop_offset = 0; // will be set for first oop field
 
-#ifndef PRODUCT
-  if( PrintCompactFieldsSavings ) {
-    next_nonstatic_double_offset = next_nonstatic_field_offset +
-                                   (nonstatic_oop_count * heapOopSize);
-    if ( nonstatic_double_count > 0 ) {
-      next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong);
-    }
-    next_nonstatic_word_offset  = next_nonstatic_double_offset +
-                                  (nonstatic_double_count * BytesPerLong);
-    next_nonstatic_short_offset = next_nonstatic_word_offset +
-                                  (nonstatic_word_count * BytesPerInt);
-    next_nonstatic_byte_offset  = next_nonstatic_short_offset +
-                                  (nonstatic_short_count * BytesPerShort);
-    next_nonstatic_type_offset  = align_size_up((next_nonstatic_byte_offset +
-                                  nonstatic_byte_count ), heapOopSize );
-    orig_nonstatic_field_size   = nonstatic_field_size +
-    ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
-  }
-#endif
   bool compact_fields   = CompactFields;
   int  allocation_style = FieldsAllocationStyle;
   if( allocation_style < 0 || allocation_style > 2 ) { // Out of range?
@@ -3264,6 +3257,7 @@
     compact_fields   = false; // Don't compact fields
   }
 
+  // Rearrange fields for a given allocation style
   if( allocation_style == 0 ) {
     // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
     next_nonstatic_oop_offset    = next_nonstatic_field_offset;
@@ -3304,6 +3298,8 @@
   int nonstatic_short_space_offset;
   int nonstatic_byte_space_offset;
 
+  // Try to squeeze some of the fields into the gaps due to
+  // long/double alignment.
   if( nonstatic_double_count > 0 ) {
     int offset = next_nonstatic_double_offset;
     next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
@@ -3413,9 +3409,11 @@
             int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
             heapOopSize ) {
           // Extend current oop map
+          assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
           nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
         } else {
           // Create new oop map
+          assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
           nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
           nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
           nonstatic_oop_map_count += 1;
@@ -3473,12 +3471,10 @@
   //
   // Additionally, this should not break alignment for the fields, so we round the alignment up
   // for each field.
-  if (contended_count > 0) {
+  if (nonstatic_contended_count > 0) {
 
     // if there is at least one contended field, we need to have pre-padding for them
-    if (nonstatic_contended_count > 0) {
-      next_nonstatic_padded_offset += pad_size;
-    }
+    next_nonstatic_padded_offset += ContendedPaddingWidth;
 
     // collect all contended groups
     BitMap bm(_cp->size());
@@ -3539,6 +3535,7 @@
             next_nonstatic_padded_offset += heapOopSize;
 
             // Create new oop map
+            assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
             nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
             nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
             nonstatic_oop_map_count += 1;
@@ -3556,7 +3553,7 @@
           // the fields within the same contended group are not inter-padded.
           // The only exception is default group, which does not incur the
           // equivalence, and so requires intra-padding.
-          next_nonstatic_padded_offset += pad_size;
+          next_nonstatic_padded_offset += ContendedPaddingWidth;
         }
 
         fs.set_offset(real_offset);
@@ -3568,67 +3565,59 @@
       // subclass fields and/or adjacent object.
       // If this was the default group, the padding is already in place.
       if (current_group != 0) {
-        next_nonstatic_padded_offset += pad_size;
+        next_nonstatic_padded_offset += ContendedPaddingWidth;
       }
     }
 
     // handle static fields
   }
 
-  // Size of instances
-  int notaligned_offset = next_nonstatic_padded_offset;
-
   // Entire class is contended, pad in the back.
   // This helps to alleviate memory contention effects for subclass fields
   // and/or adjacent object.
-  if (parsed_annotations->is_contended()) {
-    notaligned_offset += pad_size;
+  if (is_contended_class) {
+    next_nonstatic_padded_offset += ContendedPaddingWidth;
   }
 
-  int next_static_type_offset     = align_size_up(next_static_byte_offset, wordSize);
-  int static_field_size           = (next_static_type_offset -
-                                InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
-
-  next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
-  nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
-                                 - first_nonstatic_field_offset)/heapOopSize);
-
-  next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
-  int instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
+  int notaligned_nonstatic_fields_end = next_nonstatic_padded_offset;
+
+  int nonstatic_fields_end      = align_size_up(notaligned_nonstatic_fields_end, heapOopSize);
+  int instance_end              = align_size_up(notaligned_nonstatic_fields_end, wordSize);
+  int static_fields_end         = align_size_up(next_static_byte_offset, wordSize);
+
+  int static_field_size         = (static_fields_end -
+                                   InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
+  nonstatic_field_size          = nonstatic_field_size +
+                                  (nonstatic_fields_end - nonstatic_fields_start) / heapOopSize;
+
+  int instance_size             = align_object_size(instance_end / wordSize);
 
   assert(instance_size == align_object_size(align_size_up(
-         (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations->is_contended()) ? pad_size : 0)),
+         (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize),
           wordSize) / wordSize), "consistent layout helper value");
 
+  // Invariant: nonstatic_field end/start should only change if there are
+  // nonstatic fields in the class, or if the class is contended. We compare
+  // against the non-aligned value, so that end alignment will not fail the
+  // assert without actually having the fields.
+  assert((notaligned_nonstatic_fields_end == nonstatic_fields_start) ||
+         is_contended_class ||
+         (nonstatic_fields_count > 0), "double-check nonstatic start/end");
+
   // Number of non-static oop map blocks allocated at end of klass.
   const unsigned int total_oop_map_count =
     compute_oop_map_count(_super_klass, nonstatic_oop_map_count,
                           first_nonstatic_oop_offset);
 
 #ifndef PRODUCT
-  if( PrintCompactFieldsSavings ) {
-    ResourceMark rm;
-    if( nonstatic_field_size < orig_nonstatic_field_size ) {
-      tty->print("[Saved %d of %d bytes in %s]\n",
-               (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
-               orig_nonstatic_field_size*heapOopSize,
-               _class_name);
-    } else if( nonstatic_field_size > orig_nonstatic_field_size ) {
-      tty->print("[Wasted %d over %d bytes in %s]\n",
-               (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
-               orig_nonstatic_field_size*heapOopSize,
-               _class_name);
-    }
-  }
-
   if (PrintFieldLayout) {
     print_field_layout(_class_name,
           _fields,
           _cp,
           instance_size,
-          first_nonstatic_field_offset,
-          next_nonstatic_field_offset,
-          next_static_type_offset);
+          nonstatic_fields_start,
+          nonstatic_fields_end,
+          static_fields_end);
   }
 
 #endif
@@ -3837,7 +3826,7 @@
     }
 
     if (TraceClassLoadingPreorder) {
-      tty->print("[Loading %s", name->as_klass_external_name());
+      tty->print("[Loading %s", (name != NULL) ? name->as_klass_external_name() : "NoName");
       if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
       tty->print_cr("]");
     }
@@ -4076,6 +4065,9 @@
       }
     }
 
+    // Allocate mirror and initialize static fields
+    java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle));
+
 
 #ifdef ASSERT
     if (ParseAllGenericSignatures) {
@@ -4091,17 +4083,6 @@
           this_klass(), &all_mirandas, CHECK_(nullHandle));
     }
 
-    // Allocate mirror and initialize static fields
-    java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
-
-    // Allocate a simple java object for locking during class initialization.
-    // This needs to be a java object because it can be held across a java call.
-    typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_NULL);
-    this_klass->set_init_lock(r);
-
-    // TODO: Move these oops to the mirror
-    this_klass->set_protection_domain(protection_domain());
-
     // Update the loader_data graph.
     record_defined_class_dependencies(this_klass, CHECK_NULL);