changeset 973:ad6585fd4087

6830542: Performance: JVM_DefineClass already verified. Reviewed-by: kamg, phh
author acorn
date Fri, 04 Sep 2009 12:53:02 -0400
parents 6918603297f7
children 26b774d693aa
files make/linux/makefiles/mapfile-vers-debug make/linux/makefiles/mapfile-vers-product make/solaris/makefiles/mapfile-vers src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classFileParser.hpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp src/share/vm/code/dependencies.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/oops/instanceKlassKlass.cpp src/share/vm/prims/jni.cpp src/share/vm/prims/jvm.cpp src/share/vm/prims/jvm.h src/share/vm/prims/jvmtiRedefineClasses.cpp src/share/vm/runtime/vmStructs.cpp
diffstat 19 files changed, 105 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/make/linux/makefiles/mapfile-vers-debug	Tue Sep 01 23:34:08 2009 -0700
+++ b/make/linux/makefiles/mapfile-vers-debug	Fri Sep 04 12:53:02 2009 -0400
@@ -74,6 +74,7 @@
                 JVM_CurrentTimeMillis;
                 JVM_DefineClass;
                 JVM_DefineClassWithSource;
+                JVM_DefineClassWithSourceCond;
                 JVM_DesiredAssertionStatus;
                 JVM_DisableCompiler;
                 JVM_DoPrivileged;
--- a/make/linux/makefiles/mapfile-vers-product	Tue Sep 01 23:34:08 2009 -0700
+++ b/make/linux/makefiles/mapfile-vers-product	Fri Sep 04 12:53:02 2009 -0400
@@ -74,6 +74,7 @@
                 JVM_CurrentTimeMillis;
                 JVM_DefineClass;
                 JVM_DefineClassWithSource;
+                JVM_DefineClassWithSourceCond;
                 JVM_DesiredAssertionStatus;
                 JVM_DisableCompiler;
                 JVM_DoPrivileged;
--- a/make/solaris/makefiles/mapfile-vers	Tue Sep 01 23:34:08 2009 -0700
+++ b/make/solaris/makefiles/mapfile-vers	Fri Sep 04 12:53:02 2009 -0400
@@ -74,6 +74,7 @@
 		JVM_CurrentTimeMillis;
 		JVM_DefineClass;
 		JVM_DefineClassWithSource;
+		JVM_DefineClassWithSourceCond;
 		JVM_DesiredAssertionStatus;
 		JVM_DisableCompiler;
 		JVM_DoPrivileged;
--- a/src/share/vm/classfile/classFileParser.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -2547,6 +2547,7 @@
                                                     KlassHandle host_klass,
                                                     GrowableArray<Handle>* cp_patches,
                                                     symbolHandle& parsed_name,
+                                                    bool verify,
                                                     TRAPS) {
   // So that JVMTI can cache class file in the state before retransformable agents
   // have modified it
@@ -2591,7 +2592,7 @@
   instanceKlassHandle nullHandle;
 
   // Figure out whether we can skip format checking (matching classic VM behavior)
-  _need_verify = Verifier::should_verify_for(class_loader());
+  _need_verify = Verifier::should_verify_for(class_loader(), verify);
 
   // Set the verify flag in stream
   cfs->set_verify(_need_verify);
@@ -3205,6 +3206,9 @@
 
     // Fill in information already parsed
     this_klass->set_access_flags(access_flags);
+    if (verify) {
+      this_klass->set_should_verify_class();
+    }
     jint lh = Klass::instance_layout_helper(instance_size, false);
     this_klass->set_layout_helper(lh);
     assert(this_klass->oop_is_instance(), "layout is correct");
@@ -3213,7 +3217,9 @@
     //this_klass->set_super(super_klass());
     this_klass->set_class_loader(class_loader());
     this_klass->set_nonstatic_field_size(nonstatic_field_size);
-    this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
+    if (has_nonstatic_fields) {
+       this_klass->set_has_nonstatic_fields();
+    }
     this_klass->set_static_oop_field_size(fac.static_oop_count);
     cp->set_pool_holder(this_klass());
     this_klass->set_constants(cp());
--- a/src/share/vm/classfile/classFileParser.hpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/classFileParser.hpp	Fri Sep 04 12:53:02 2009 -0400
@@ -257,9 +257,10 @@
                                      Handle class_loader,
                                      Handle protection_domain,
                                      symbolHandle& parsed_name,
+                                     bool verify,
                                      TRAPS) {
     KlassHandle no_host_klass;
-    return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD);
+    return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
   }
   instanceKlassHandle parseClassFile(symbolHandle name,
                                      Handle class_loader,
@@ -267,6 +268,7 @@
                                      KlassHandle host_klass,
                                      GrowableArray<Handle>* cp_patches,
                                      symbolHandle& parsed_name,
+                                     bool verify,
                                      TRAPS);
 
   // Verifier checks
--- a/src/share/vm/classfile/classLoader.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/classLoader.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -874,6 +874,7 @@
                                                        class_loader,
                                                        protection_domain,
                                                        parsed_name,
+                                                       false,
                                                        CHECK_(h));
 
     // add to package table
--- a/src/share/vm/classfile/systemDictionary.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/systemDictionary.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -970,6 +970,7 @@
                                                              host_klass,
                                                              cp_patches,
                                                              parsed_name,
+                                                             true,
                                                              THREAD);
 
 
@@ -1025,6 +1026,7 @@
                                                Handle class_loader,
                                                Handle protection_domain,
                                                ClassFileStream* st,
+                                               bool verify,
                                                TRAPS) {
 
   // Classloaders that support parallelism, e.g. bootstrap classloader,
@@ -1055,6 +1057,7 @@
                                                              class_loader,
                                                              protection_domain,
                                                              parsed_name,
+                                                             verify,
                                                              THREAD);
 
   const char* pkg = "java/";
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Sep 04 12:53:02 2009 -0400
@@ -259,7 +259,9 @@
                                TRAPS);
 
   // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
-  static klassOop resolve_from_stream(symbolHandle class_name, Handle class_loader, Handle protection_domain, ClassFileStream* st, TRAPS);
+  static klassOop resolve_from_stream(symbolHandle class_name, Handle class_loader,
+                                      Handle protection_domain,
+                                      ClassFileStream* st, bool verify, TRAPS);
 
   // Lookup an already loaded class. If not found NULL is returned.
   static klassOop find(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
--- a/src/share/vm/classfile/verifier.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/verifier.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -53,8 +53,8 @@
 
 // Methods in Verifier
 
-bool Verifier::should_verify_for(oop class_loader) {
-  return class_loader == NULL ?
+bool Verifier::should_verify_for(oop class_loader, bool should_verify_class) {
+  return (class_loader == NULL || !should_verify_class) ?
     BytecodeVerificationLocal : BytecodeVerificationRemote;
 }
 
@@ -68,7 +68,7 @@
   return !need_verify;
 }
 
-bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, TRAPS) {
+bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
   ResourceMark rm(THREAD);
   HandleMark hm;
 
@@ -81,7 +81,7 @@
   // If the class should be verified, first see if we can use the split
   // verifier.  If not, or if verification fails and FailOverToOldVerifier
   // is set, then call the inference verifier.
-  if (is_eligible_for_verification(klass)) {
+  if (is_eligible_for_verification(klass, should_verify_class)) {
     if (TraceClassInitialization) {
       tty->print_cr("Start class verification for: %s", klassName);
     }
@@ -141,12 +141,13 @@
   }
 }
 
-bool Verifier::is_eligible_for_verification(instanceKlassHandle klass) {
+bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
   symbolOop name = klass->name();
   klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass();
 
-  return (should_verify_for(klass->class_loader()) &&
+  return (should_verify_for(klass->class_loader(), should_verify_class) &&
     // return if the class is a bootstrapping class
+    // or defineClass specified not to verify by default (flags override passed arg)
     // We need to skip the following four for bootstraping
     name != vmSymbols::java_lang_Object() &&
     name != vmSymbols::java_lang_Class() &&
--- a/src/share/vm/classfile/verifier.hpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/classfile/verifier.hpp	Fri Sep 04 12:53:02 2009 -0400
@@ -34,16 +34,18 @@
    * Otherwise, no exception is thrown and the return indicates the
    * error.
    */
-  static bool verify(instanceKlassHandle klass, Mode mode, TRAPS);
+  static bool verify(instanceKlassHandle klass, Mode mode, bool should_verify_class, TRAPS);
 
-  // Return false if the class is loaded by the bootstrap loader.
-  static bool should_verify_for(oop class_loader);
+  // Return false if the class is loaded by the bootstrap loader,
+  // or if defineClass was called requesting skipping verification
+  // -Xverify:all/none override this value
+  static bool should_verify_for(oop class_loader, bool should_verify_class);
 
   // Relax certain verifier checks to enable some broken 1.1 apps to run on 1.2.
   static bool relax_verify_for(oop class_loader);
 
  private:
-  static bool is_eligible_for_verification(instanceKlassHandle klass);
+  static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class);
   static symbolHandle inference_verify(
     instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);
 };
--- a/src/share/vm/code/dependencies.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/code/dependencies.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -1464,7 +1464,7 @@
   for (ContextStream str(*this); str.next(); ) {
     klassOop d = str.klass();
     assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking");
-    instanceKlass::cast(d)->set_is_marked_dependent(true);
+    instanceKlass::cast(d)->set_is_marked_dependent();
   }
 }
 
@@ -1473,7 +1473,7 @@
   // Unmark transitive interfaces
   for (ContextStream str(*this); str.next(); ) {
     klassOop d = str.klass();
-    instanceKlass::cast(d)->set_is_marked_dependent(false);
+    instanceKlass::cast(d)->clear_is_marked_dependent();
   }
 }
 
--- a/src/share/vm/oops/instanceKlass.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -110,7 +110,7 @@
   // 1) Verify the bytecodes
   Verifier::Mode mode =
     throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
-  return Verifier::verify(this_oop, mode, CHECK_false);
+  return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), CHECK_false);
 }
 
 
--- a/src/share/vm/oops/instanceKlass.hpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Fri Sep 04 12:53:02 2009 -0400
@@ -114,6 +114,15 @@
     initialization_error                // error happened during initialization
   };
 
+  // smaller footprint for boolean flags
+  enum ClassFlags {
+    _noflags           = 0,             // initial value
+    _rewritten         = 0x00000001U,   // rewritten
+    _should_verify     = 0x00000002U,   // defineClass specified conditional verification
+    _has_nonstatic_fields = 0x00000004U, // for sizing with UseCompressedOops
+    _is_marked_dependent = 0x00000008U  // used for marking during flushing and deoptimization
+   };
+
  public:
   oop* oop_block_beg() const { return adr_array_klasses(); }
   oop* oop_block_end() const { return adr_methods_default_annotations() + 1; }
@@ -192,9 +201,7 @@
   int             _static_field_size;    // number words used by static fields (oop and non-oop) in this klass
   int             _static_oop_field_size;// number of static oop fields in this klass
   int             _nonstatic_oop_map_size;// number of nonstatic oop-map blocks allocated at end of this klass
-  bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
-  bool            _rewritten;            // methods rewritten.
-  bool            _has_nonstatic_fields; // for sizing with UseCompressedOops
+  int             _class_flags;          // internal class state flags
   u2              _minor_version;        // minor version number of class file
   u2              _major_version;        // major version number of class file
   ClassState      _init_state;           // state of class
@@ -230,8 +237,8 @@
   friend class SystemDictionary;
 
  public:
-  bool has_nonstatic_fields() const        { return _has_nonstatic_fields; }
-  void set_has_nonstatic_fields(bool b)    { _has_nonstatic_fields = b; }
+  bool has_nonstatic_fields() const        { return (_class_flags & _has_nonstatic_fields) != 0; }
+  void set_has_nonstatic_fields()          { _class_flags |= _has_nonstatic_fields; }
 
   // field sizes
   int nonstatic_field_size() const         { return _nonstatic_field_size; }
@@ -338,11 +345,16 @@
   bool is_in_error_state() const           { return _init_state == initialization_error; }
   bool is_reentrant_initialization(Thread *thread)  { return thread == _init_thread; }
   int  get_init_state()                    { return _init_state; } // Useful for debugging
-  bool is_rewritten() const                { return _rewritten; }
+  bool is_rewritten() const                { return (_class_flags & _rewritten) != 0; }
+
+  // defineClass specified verification
+  bool should_verify_class() const         { return (_class_flags & _should_verify) != 0; }
+  void set_should_verify_class()           { _class_flags |= _should_verify; }
 
   // marking
-  bool is_marked_dependent() const         { return _is_marked_dependent; }
-  void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
+  bool is_marked_dependent() const         { return (_class_flags & _is_marked_dependent) != 0; }
+  void set_is_marked_dependent()           { _class_flags |= _is_marked_dependent; }
+  void clear_is_marked_dependent()         { _class_flags &= ~_is_marked_dependent; }
 
   // initialization (virtuals from Klass)
   bool should_be_initialized() const;  // means that initialize should be called
@@ -715,7 +727,8 @@
 #else
   void set_init_state(ClassState state) { _init_state = state; }
 #endif
-  void set_rewritten()                  { _rewritten = true; }
+  void clear_class_flags()              { _class_flags = _noflags; }
+  void set_rewritten()                  { _class_flags |= _rewritten; }
   void set_init_thread(Thread *thread)  { _init_thread = thread; }
 
   u2 idnum_allocated_count() const      { return _idnum_allocated_count; }
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -450,9 +450,9 @@
     ik->set_inner_classes(NULL);
     ik->set_static_oop_field_size(0);
     ik->set_nonstatic_field_size(0);
-    ik->set_is_marked_dependent(false);
     ik->set_init_state(instanceKlass::allocated);
     ik->set_init_thread(NULL);
+    ik->clear_class_flags();
     ik->set_reference_type(rt);
     ik->set_oop_map_cache(NULL);
     ik->set_jni_ids(NULL);
--- a/src/share/vm/prims/jni.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/prims/jni.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -299,7 +299,8 @@
     }
   }
   klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
-                                                     Handle(), &st, CHECK_NULL);
+                                                     Handle(), &st, true,
+                                                     CHECK_NULL);
 
   if (TraceClassResolution && k != NULL) {
     trace_class_resolution(k);
--- a/src/share/vm/prims/jvm.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/prims/jvm.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -762,7 +762,11 @@
 }
 
 // common code for JVM_DefineClass() and JVM_DefineClassWithSource()
-static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
+// and JVM_DefineClassWithSourceCond()
+static jclass jvm_define_class_common(JNIEnv *env, const char *name,
+                                      jobject loader, const jbyte *buf,
+                                      jsize len, jobject pd, const char *source,
+                                      jboolean verify, TRAPS) {
   if (source == NULL)  source = "__JVM_DefineClass__";
 
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -803,6 +807,7 @@
   Handle protection_domain (THREAD, JNIHandles::resolve(pd));
   klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
                                                      protection_domain, &st,
+                                                     verify != 0,
                                                      CHECK_NULL);
 
   if (TraceClassResolution && k != NULL) {
@@ -816,16 +821,24 @@
 JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
   JVMWrapper2("JVM_DefineClass %s", name);
 
-  return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD);
+  return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, true, THREAD);
 JVM_END
 
 
 JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source))
   JVMWrapper2("JVM_DefineClassWithSource %s", name);
 
-  return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD);
-JVM_END
-
+  return jvm_define_class_common(env, name, loader, buf, len, pd, source, true, THREAD);
+JVM_END
+
+JVM_ENTRY(jclass, JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
+                                                jobject loader, const jbyte *buf,
+                                                jsize len, jobject pd,
+                                                const char *source, jboolean verify))
+  JVMWrapper2("JVM_DefineClassWithSourceCond %s", name);
+
+  return jvm_define_class_common(env, name, loader, buf, len, pd, source, verify, THREAD);
+JVM_END
 
 JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
   JVMWrapper("JVM_FindLoadedClass");
--- a/src/share/vm/prims/jvm.h	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/prims/jvm.h	Fri Sep 04 12:53:02 2009 -0400
@@ -417,6 +417,17 @@
                           const jbyte *buf, jsize len, jobject pd,
                           const char *source);
 
+/* Define a class with a source with conditional verification (added HSX 14)
+ * -Xverify:all will verify anyway, -Xverify:none will not verify,
+ * -Xverify:remote (default) will obey this conditional
+ * i.e. true = should_verify_class
+ */
+JNIEXPORT jclass JNICALL
+JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
+                              jobject loader, const jbyte *buf,
+                              jsize len, jobject pd, const char *source,
+                              jboolean verify);
+
 /* Define a class with a source (MLVM) */
 JNIEXPORT jclass JNICALL
 JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader,
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -933,7 +933,7 @@
       // description.
       RedefineVerifyMark rvm(&the_class, &scratch_class, state);
       Verifier::verify(
-        scratch_class, Verifier::ThrowException, THREAD);
+        scratch_class, Verifier::ThrowException, true, THREAD);
     }
 
     if (HAS_PENDING_EXCEPTION) {
@@ -959,7 +959,7 @@
       // verify what we have done during constant pool merging
       {
         RedefineVerifyMark rvm(&the_class, &scratch_class, state);
-        Verifier::verify(scratch_class, Verifier::ThrowException, THREAD);
+        Verifier::verify(scratch_class, Verifier::ThrowException, true, THREAD);
       }
 
       if (HAS_PENDING_EXCEPTION) {
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Sep 01 23:34:08 2009 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Fri Sep 04 12:53:02 2009 -0400
@@ -108,7 +108,7 @@
   nonstatic_field(instanceKlass,               _static_field_size,                            int)                                   \
   nonstatic_field(instanceKlass,               _static_oop_field_size,                        int)                                   \
   nonstatic_field(instanceKlass,               _nonstatic_oop_map_size,                       int)                                   \
-  nonstatic_field(instanceKlass,               _is_marked_dependent,                          bool)                                  \
+  nonstatic_field(instanceKlass,               _class_flags,                                  int)                                   \
   nonstatic_field(instanceKlass,               _minor_version,                                u2)                                    \
   nonstatic_field(instanceKlass,               _major_version,                                u2)                                    \
   nonstatic_field(instanceKlass,               _init_state,                                   instanceKlass::ClassState)             \
@@ -1245,6 +1245,7 @@
    declare_integer_type(Bytecodes::Code)                                  \
    declare_integer_type(Generation::Name)                                 \
    declare_integer_type(instanceKlass::ClassState)                        \
+   declare_integer_type(instanceKlass::ClassFlags)                        \
    declare_integer_type(JavaThreadState)                                  \
    declare_integer_type(Location::Type)                                   \
    declare_integer_type(Location::Where)                                  \
@@ -1526,6 +1527,16 @@
   declare_constant(instanceKlass::initialization_error)                   \
                                                                           \
   /*********************************/                                     \
+  /* instanceKlass ClassFlags enum */                                     \
+  /*********************************/                                     \
+                                                                          \
+  declare_constant(instanceKlass::_noflags)                               \
+  declare_constant(instanceKlass::_rewritten)                             \
+  declare_constant(instanceKlass::_should_verify)                         \
+  declare_constant(instanceKlass::_has_nonstatic_fields)                  \
+  declare_constant(instanceKlass::_is_marked_dependent)                   \
+                                                                          \
+  /*********************************/                                     \
   /* symbolOop - symbol max length */                                     \
   /*********************************/                                     \
                                                                           \