6956164: nightly regressions from 6939207
authorjrose
Thu, 27 May 2010 09:54:07 -0700
changeset 5693 3015c564fcbc
parent 5692 5ab61a141f2f
child 5694 1e0532a6abff
6956164: nightly regressions from 6939207 Summary: Fix errors in 6939207. Reviewed-by: kvn
hotspot/src/share/vm/classfile/verifier.cpp
hotspot/src/share/vm/classfile/verifier.hpp
hotspot/src/share/vm/interpreter/bytecodeStream.hpp
hotspot/src/share/vm/interpreter/bytecodes.cpp
hotspot/src/share/vm/interpreter/bytecodes.hpp
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Tue May 25 13:18:49 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Thu May 27 09:54:07 2010 -0700
@@ -254,6 +254,9 @@
   int num_methods = methods->length();
 
   for (int index = 0; index < num_methods; index++) {
+    // Check for recursive re-verification before each method.
+    if (was_recursively_verified())  return;
+
     methodOop m = (methodOop)methods->obj_at(index);
     if (m->is_native() || m->is_abstract()) {
       // If m is native or abstract, skip it.  It is checked in class file
@@ -262,6 +265,12 @@
     }
     verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
   }
+
+  if (_verify_verbose || TraceClassInitialization) {
+    if (was_recursively_verified())
+      tty->print_cr("Recursive verification detected for: %s",
+          _klass->external_name());
+  }
 }
 
 void ClassVerifier::verify_method(methodHandle m, TRAPS) {
@@ -326,6 +335,9 @@
                                 // instruction in sequence
   Bytecodes::Code opcode;
   while (!bcs.is_last_bytecode()) {
+    // Check for recursive re-verification before each bytecode.
+    if (was_recursively_verified())  return;
+
     opcode = bcs.raw_next();
     u2 bci = bcs.bci();
 
@@ -1470,20 +1482,9 @@
 
   // In some situations, bytecode rewriting may occur while we're verifying.
   // In this case, a constant pool cache exists and some indices refer to that
-  // instead.  Get the original index for the tag check
-  constantPoolCacheOop cache = cp->cache();
-  if (cache != NULL &&
-       ((types == (1 <<  JVM_CONSTANT_InterfaceMethodref)) ||
-        (types == (1 <<  JVM_CONSTANT_Methodref)) ||
-        (types == (1 <<  JVM_CONSTANT_Fieldref)))) {
-    int native_index = index;
-    if (Bytes::is_Java_byte_ordering_different()) {
-      native_index = Bytes::swap_u2(index);
-    }
-    assert((native_index >= 0) && (native_index < cache->length()),
-      "Must be a legal index into the cp cache");
-    index = cache->entry_at(native_index)->constant_pool_index();
-  }
+  // instead.  Be sure we don't pick up such indices by accident.
+  // We must check was_recursively_verified() before we get here.
+  guarantee(cp->cache() == NULL, "not rewritten yet");
 
   verify_cp_index(cp, index, CHECK_VERIFY(this));
   unsigned int tag = cp->tag_at(index).value();
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Tue May 25 13:18:49 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Thu May 27 09:54:07 2010 -0700
@@ -158,6 +158,16 @@
   methodHandle        _method; // current method being verified
   VerificationType    _this_type; // the verification type of the current class
 
+  // Some recursive calls from the verifier to the name resolver
+  // can cause the current class to be re-verified and rewritten.
+  // If this happens, the original verification should not continue,
+  // because constant pool indexes will have changed.
+  // The rewriter is preceded by the verifier.  If the verifier throws
+  // an error, rewriting is prevented.  Also, rewriting always precedes
+  // bytecode execution or compilation.  Thus, is_rewritten implies
+  // that a class has been verified and prepared for execution.
+  bool was_recursively_verified() { return _klass->is_rewritten(); }
+
  public:
   enum {
     BYTECODE_OFFSET = 1,
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Tue May 25 13:18:49 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Thu May 27 09:54:07 2010 -0700
@@ -212,5 +212,5 @@
                                                    return bytecode()->get_index_u2_cpcache(raw_code()); }
   int             get_index_u4() const           { assert_raw_stream(false);
                                                    return bytecode()->get_index_u4(raw_code()); }
-  int             has_index_u4() const           { return bytecode()->get_index_u4(raw_code()); }
+  bool            has_index_u4() const           { return bytecode()->has_index_u4(raw_code()); }
 };
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp	Tue May 25 13:18:49 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp	Thu May 27 09:54:07 2010 -0700
@@ -86,6 +86,7 @@
       return (len > 0 && len == (int)len) ? len : -1;
     }
   }
+  // Note: Length functions must return <=0 for invalid bytecodes.
   return 0;
 }
 
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Tue May 25 13:18:49 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Thu May 27 09:54:07 2010 -0700
@@ -353,8 +353,10 @@
   static const char* name           (Code code)    { check(code);      return _name          [code]; }
   static BasicType   result_type    (Code code)    { check(code);      return _result_type   [code]; }
   static int         depth          (Code code)    { check(code);      return _depth         [code]; }
-  static int         length_for     (Code code)    { check(code);      return _lengths       [code] & 0xF; }
-  static int         wide_length_for(Code code)    { check(code);      return _lengths       [code] >> 4; }
+  // Note: Length functions must return <=0 for invalid bytecodes.
+  // Calling check(code) in length functions would throw an unwanted assert.
+  static int         length_for     (Code code)    { /*no check*/      return _lengths       [code] & 0xF; }
+  static int         wide_length_for(Code code)    { /*no check*/      return _lengths       [code] >> 4; }
   static bool        can_trap       (Code code)    { check(code);      return has_all_flags(code, _bc_can_trap, false); }
   static Code        java_code      (Code code)    { check(code);      return _java_code     [code]; }
   static bool        can_rewrite    (Code code)    { check(code);      return has_all_flags(code, _bc_can_rewrite, false); }