hotspot/src/share/vm/classfile/verifier.cpp
changeset 8076 96d498ec7ae1
parent 7405 e6fc8d3926f8
child 8107 78e5bd944384
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jan 27 13:42:28 2011 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jan 27 16:11:27 2011 -0800
@@ -98,10 +98,10 @@
 }
 
 bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
+  HandleMark hm;
   ResourceMark rm(THREAD);
-  HandleMark hm;
 
-  symbolHandle exception_name;
+  Symbol* exception_name = NULL;
   const size_t message_buffer_len = klass->name()->utf8_length() + 1024;
   char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
 
@@ -141,7 +141,7 @@
         tty->print("Verification for %s has", klassName);
         tty->print_cr(" exception pending %s ",
           instanceKlass::cast(PENDING_EXCEPTION->klass())->external_name());
-      } else if (!exception_name.is_null()) {
+      } else if (exception_name != NULL) {
         tty->print_cr("Verification for %s failed", klassName);
       }
       tty->print_cr("End class verification for: %s", klassName);
@@ -150,7 +150,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     return false; // use the existing exception
-  } else if (exception_name.is_null()) {
+  } else if (exception_name == NULL) {
     return true; // verifcation succeeded
   } else { // VerifyError or ClassFormatError to be created and thrown
     ResourceMark rm(THREAD);
@@ -172,7 +172,7 @@
 }
 
 bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
-  symbolOop name = klass->name();
+  Symbol* name = klass->name();
   klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass();
 
   return (should_verify_for(klass->class_loader(), should_verify_class) &&
@@ -202,7 +202,7 @@
   );
 }
 
-symbolHandle Verifier::inference_verify(
+Symbol* Verifier::inference_verify(
     instanceKlassHandle klass, char* message, size_t message_len, TRAPS) {
   JavaThread* thread = (JavaThread*)THREAD;
   JNIEnv *env = thread->jni_environment();
@@ -245,18 +245,17 @@
   // These numbers are chosen so that VerifyClassCodes interface doesn't need
   // to be changed (still return jboolean (unsigned char)), and result is
   // 1 when verification is passed.
-  symbolHandle nh(NULL);
   if (result == 0) {
     return vmSymbols::java_lang_VerifyError();
   } else if (result == 1) {
-    return nh; // verified.
+    return NULL; // verified.
   } else if (result == 2) {
-    THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, nh);
+    THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, NULL);
   } else if (result == 3) {
     return vmSymbols::java_lang_ClassFormatError();
   } else {
     ShouldNotReachHere();
-    return nh;
+    return NULL;
   }
 }
 
@@ -266,12 +265,19 @@
 
 ClassVerifier::ClassVerifier(
     instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS)
-    : _thread(THREAD), _exception_type(symbolHandle()), _message(msg),
+    : _thread(THREAD), _exception_type(NULL), _message(msg),
       _message_buffer_len(msg_len), _klass(klass) {
   _this_type = VerificationType::reference_type(klass->name());
+  // Create list to hold symbols in reference area.
+  _symbols = new GrowableArray<Symbol*>(100, 0, NULL);
 }
 
 ClassVerifier::~ClassVerifier() {
+  // Decrement the reference count for any symbols created.
+  for (int i = 0; i < _symbols->length(); i++) {
+    Symbol* s = _symbols->at(i);
+    s->decrement_refcount();
+  }
 }
 
 VerificationType ClassVerifier::object_type() const {
@@ -308,7 +314,6 @@
 }
 
 void ClassVerifier::verify_method(methodHandle m, TRAPS) {
-  ResourceMark rm(THREAD);
   _method = m;   // initialize _method
   if (_verify_verbose) {
     tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string());
@@ -615,7 +620,7 @@
               VerificationType::null_type(), CHECK_VERIFY(this));
           } else {
             VerificationType component =
-              atype.get_component(CHECK_VERIFY(this));
+              atype.get_component(this, CHECK_VERIFY(this));
             current_frame.push_stack(component, CHECK_VERIFY(this));
           }
           no_control_flow = false; break;
@@ -1386,7 +1391,7 @@
         VerificationType throwable =
           VerificationType::reference_type(vmSymbols::java_lang_Throwable());
         bool is_subclass = throwable.is_assignable_from(
-          catch_type, current_class(), CHECK_VERIFY(this));
+          catch_type, this, CHECK_VERIFY(this));
         if (!is_subclass) {
           // 4286534: should throw VerifyError according to recent spec change
           verify_error(
@@ -1473,8 +1478,6 @@
       if(bci >= start_pc && bci < end_pc) {
         u1 flags = current_frame->flags();
         if (this_uninit) {  flags |= FLAG_THIS_UNINIT; }
-
-        ResourceMark rm(THREAD);
         StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
         if (catch_type_index != 0) {
           // We know that this index refers to a subclass of Throwable
@@ -1575,7 +1578,7 @@
   va_end(va);
 }
 
-klassOop ClassVerifier::load_class(symbolHandle name, TRAPS) {
+klassOop ClassVerifier::load_class(Symbol* name, TRAPS) {
   // Get current loader and protection domain first.
   oop loader = current_class()->class_loader();
   oop protection_domain = current_class()->protection_domain();
@@ -1587,8 +1590,8 @@
 
 bool ClassVerifier::is_protected_access(instanceKlassHandle this_class,
                                         klassOop target_class,
-                                        symbolOop field_name,
-                                        symbolOop field_sig,
+                                        Symbol* field_name,
+                                        Symbol* field_sig,
                                         bool is_method) {
   No_Safepoint_Verifier nosafepoint;
 
@@ -1736,7 +1739,7 @@
 }
 
 bool ClassVerifier::name_in_supers(
-    symbolOop ref_name, instanceKlassHandle current) {
+    Symbol* ref_name, instanceKlassHandle current) {
   klassOop super = current->super();
   while (super != NULL) {
     if (super->klass_part()->name() == ref_name) {
@@ -1755,8 +1758,8 @@
   verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this));
 
   // Get field name and signature
-  symbolHandle field_name = symbolHandle(THREAD, cp->name_ref_at(index));
-  symbolHandle field_sig = symbolHandle(THREAD, cp->signature_ref_at(index));
+  Symbol* field_name = cp->name_ref_at(index);
+  Symbol* field_sig = cp->signature_ref_at(index);
 
   if (!SignatureVerifier::is_valid_type_signature(field_sig)) {
     class_format_error(
@@ -1823,11 +1826,11 @@
       fieldDescriptor fd;
       if (stack_object_type == VerificationType::uninitialized_this_type() &&
           target_class_type.equals(current_type()) &&
-          _klass->find_local_field(field_name(), field_sig(), &fd)) {
+          _klass->find_local_field(field_name, field_sig, &fd)) {
         stack_object_type = current_type();
       }
       is_assignable = target_class_type.is_assignable_from(
-        stack_object_type, current_class(), CHECK_VERIFY(this));
+        stack_object_type, this, CHECK_VERIFY(this));
       if (!is_assignable) {
         verify_error(bci, "Bad type on operand stack in putfield");
         return;
@@ -1836,9 +1839,9 @@
     check_protected: {
       if (_this_type == stack_object_type)
         break; // stack_object_type must be assignable to _current_class_type
-      symbolHandle ref_class_name = symbolHandle(THREAD,
-        cp->klass_name_at(cp->klass_ref_index_at(index)));
-      if (!name_in_supers(ref_class_name(), current_class()))
+      Symbol* ref_class_name =
+        cp->klass_name_at(cp->klass_ref_index_at(index));
+      if (!name_in_supers(ref_class_name, current_class()))
         // stack_object_type must be assignable to _current_class_type since:
         // 1. stack_object_type must be assignable to ref_class.
         // 2. ref_class must be _current_class or a subclass of it. It can't
@@ -1846,12 +1849,12 @@
         break;
 
       klassOop ref_class_oop = load_class(ref_class_name, CHECK);
-      if (is_protected_access(current_class(), ref_class_oop, field_name(),
-                              field_sig(), false)) {
+      if (is_protected_access(current_class(), ref_class_oop, field_name,
+                              field_sig, false)) {
         // It's protected access, check if stack object is assignable to
         // current class.
         is_assignable = current_type().is_assignable_from(
-          stack_object_type, current_class(), CHECK_VERIFY(this));
+          stack_object_type, this, CHECK_VERIFY(this));
         if (!is_assignable) {
           verify_error(bci, "Bad access to protected data in getfield");
           return;
@@ -1911,7 +1914,7 @@
       instanceKlassHandle mh(THREAD, m->method_holder());
       if (m->is_protected() && !mh->is_same_class_package(_klass())) {
         bool assignable = current_type().is_assignable_from(
-          objectref_type, current_class(), CHECK_VERIFY(this));
+          objectref_type, this, CHECK_VERIFY(this));
         if (!assignable) {
           verify_error(bci, "Bad access to protected <init> method");
           return;
@@ -1941,8 +1944,8 @@
   verify_cp_type(index, cp, types, CHECK_VERIFY(this));
 
   // Get method name and signature
-  symbolHandle method_name(THREAD, cp->name_ref_at(index));
-  symbolHandle method_sig(THREAD, cp->signature_ref_at(index));
+  Symbol* method_name = cp->name_ref_at(index);
+  Symbol* method_sig = cp->signature_ref_at(index);
 
   if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
     class_format_error(
@@ -2035,7 +2038,7 @@
   if (method_name->byte_at(0) == '<') {
     // Make sure <init> can only be invoked by invokespecial
     if (opcode != Bytecodes::_invokespecial ||
-        method_name() != vmSymbols::object_initializer_name()) {
+        method_name != vmSymbols::object_initializer_name()) {
       verify_error(bci, "Illegal call to internal method");
       return;
     }
@@ -2044,7 +2047,7 @@
              && !ref_class_type.equals(VerificationType::reference_type(
                   current_class()->super()->klass_part()->name()))) {
     bool subtype = ref_class_type.is_assignable_from(
-      current_type(), current_class(), CHECK_VERIFY(this));
+      current_type(), this, CHECK_VERIFY(this));
     if (!subtype) {
       verify_error(bci, "Bad invokespecial instruction: "
           "current class isn't assignable to reference class.");
@@ -2058,7 +2061,7 @@
   // Check objectref on operand stack
   if (opcode != Bytecodes::_invokestatic &&
       opcode != Bytecodes::_invokedynamic) {
-    if (method_name() == vmSymbols::object_initializer_name()) {  // <init> method
+    if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
       verify_invoke_init(bcs, ref_class_type, current_frame,
         code_length, this_uninit, cp, CHECK_VERIFY(this));
     } else {   // other methods
@@ -2070,22 +2073,22 @@
           current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
         if (current_type() != stack_object_type) {
           assert(cp->cache() == NULL, "not rewritten yet");
-          symbolHandle ref_class_name = symbolHandle(THREAD,
-            cp->klass_name_at(cp->klass_ref_index_at(index)));
+          Symbol* ref_class_name =
+            cp->klass_name_at(cp->klass_ref_index_at(index));
           // See the comments in verify_field_instructions() for
           // the rationale behind this.
-          if (name_in_supers(ref_class_name(), current_class())) {
+          if (name_in_supers(ref_class_name, current_class())) {
             klassOop ref_class = load_class(ref_class_name, CHECK);
             if (is_protected_access(
-                  _klass, ref_class, method_name(), method_sig(), true)) {
+                  _klass, ref_class, method_name, method_sig, true)) {
               // It's protected access, check if stack object is
               // assignable to current class.
               bool is_assignable = current_type().is_assignable_from(
-                stack_object_type, current_class(), CHECK_VERIFY(this));
+                stack_object_type, this, CHECK_VERIFY(this));
               if (!is_assignable) {
                 if (ref_class_type.name() == vmSymbols::java_lang_Object()
                     && stack_object_type.is_array()
-                    && method_name() == vmSymbols::clone_name()) {
+                    && method_name == vmSymbols::clone_name()) {
                   // Special case: arrays pretend to implement public Object
                   // clone().
                 } else {
@@ -2105,7 +2108,7 @@
   }
   // Push the result type.
   if (sig_stream.type() != T_VOID) {
-    if (method_name() == vmSymbols::object_initializer_name()) {
+    if (method_name == vmSymbols::object_initializer_name()) {
       // <init> method must have a void return type
       verify_error(bci, "Return type must be void in <init> method");
       return;
@@ -2130,7 +2133,7 @@
   }
 
   // from_bt[index] contains the array signature which has a length of 2
-  symbolHandle sig = oopFactory::new_symbol_handle(
+  Symbol* sig = create_temporary_symbol(
     from_bt[index], 2, CHECK_(VerificationType::bogus_type()));
   return VerificationType::reference_type(sig);
 }
@@ -2143,7 +2146,6 @@
 
   VerificationType component_type =
     cp_index_to_type(index, cp, CHECK_VERIFY(this));
-  ResourceMark rm(THREAD);
   int length;
   char* arr_sig_str;
   if (component_type.is_array()) {     // it's an array
@@ -2163,7 +2165,7 @@
     strncpy(&arr_sig_str[2], component_name, length - 2);
     arr_sig_str[length - 1] = ';';
   }
-  symbolHandle arr_sig = oopFactory::new_symbol_handle(
+  Symbol* arr_sig = create_temporary_symbol(
     arr_sig_str, length, CHECK_VERIFY(this));
   VerificationType new_array_type = VerificationType::reference_type(arr_sig);
   current_frame->push_stack(new_array_type, CHECK_VERIFY(this));
@@ -2256,9 +2258,25 @@
     verify_error(bci, "Method expects a return value");
     return;
   }
-  bool match = return_type.is_assignable_from(type, _klass, CHECK_VERIFY(this));
+  bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this));
   if (!match) {
     verify_error(bci, "Bad return type");
     return;
   }
 }
+
+// The verifier creates symbols which are substrings of Symbols.
+// These are stored in the verifier until the end of verification so that
+// they can be reference counted.
+Symbol* ClassVerifier::create_temporary_symbol(const Symbol *s, int begin,
+                                               int end, TRAPS) {
+  Symbol* sym = SymbolTable::new_symbol(s, begin, end, CHECK_NULL);
+  _symbols->push(sym);
+  return sym;
+}
+
+Symbol* ClassVerifier::create_temporary_symbol(const char *s, int length, TRAPS) {
+  Symbol* sym = SymbolTable::new_symbol(s, length, CHECK_NULL);
+  _symbols->push(sym);
+  return sym;
+}