< prev index next >

src/hotspot/share/classfile/verifier.cpp

Print this page

        

@@ -572,11 +572,11 @@
 // Methods in ClassVerifier
 
 ClassVerifier::ClassVerifier(
     InstanceKlass* klass, TRAPS)
     : _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL),
-      _message(NULL), _klass(klass) {
+      _message(NULL), _method_signatures_table(NULL), _klass(klass) {
   _this_type = VerificationType::reference_type(klass->name());
 }
 
 ClassVerifier::~ClassVerifier() {
   // Decrement the reference count for any symbols created.

@@ -599,10 +599,18 @@
 }
 
 void ClassVerifier::verify_class(TRAPS) {
   log_info(verification)("Verifying class %s with new format", _klass->external_name());
 
+  // Either verifying both local and remote classes or just remote classes.
+  assert(BytecodeVerificationRemote, "Should not be here");
+
+  // Create and initialize hash table containing method signatures.
+  method_signatures_table_type method_signatures_table;
+  init_method_sigs_table(&method_signatures_table, CHECK_VERIFY(this));
+  set_method_signatures_table(&method_signatures_table);
+
   Array<Method*>* methods = _klass->methods();
   int num_methods = methods->length();
 
   for (int index = 0; index < num_methods; index++) {
     // Check for recursive re-verification before each method.

@@ -623,10 +631,85 @@
     log_info(class, init)("Recursive verification detected for: %s",
                         _klass->external_name());
   }
 }
 
+// Translate the signature entries into verification types and save them in
+// the growable array.  Also, save the count of arguments.
+void ClassVerifier::translate_signature(Symbol* const method_sig,
+                                        sig_as_verification_types* sig_verif_types,
+                                        TRAPS) {
+  SignatureStream sig_stream(method_sig);
+  VerificationType sig_type[2];
+  int sig_i = 0;
+  GrowableArray<VerificationType>* verif_types = sig_verif_types->sig_verif_types();
+
+  // Translate the signature arguments into verification types.
+  while (!sig_stream.at_return_type()) {
+    int n = change_sig_to_verificationType(&sig_stream, sig_type, CHECK_VERIFY(this));
+    assert(n <= 2, "Unexpected signature type");
+
+    // Store verification type(s).  Longs and Doubles each have two verificationTypes.
+    for (int x = 0; x < n; x++) {
+      verif_types->push(sig_type[x]);
+    }
+    sig_i += n;
+    sig_stream.next();
+  }
+
+  // Set final arg count, not including the return type.  The final arg count will
+  // be compared with sig_verify_types' length to see if there is a return type.
+  sig_verif_types->set_num_args(sig_i);
+
+  // Store verification type(s) for the return type, if there is one.
+  if (sig_stream.type() != T_VOID) {
+    int n = change_sig_to_verificationType(&sig_stream, sig_type, CHECK_VERIFY(this));
+    assert(n <= 2, "Unexpected signature return type");
+    for (int y = 0; y < n; y++) {
+      verif_types->push(sig_type[y]);
+    }
+  }
+}
+
+
+// Initialize the table with all the unique method signatures.
+void ClassVerifier::init_method_sigs_table(method_signatures_table_type* method_sig_table, TRAPS) {
+  ConstantPool* cp = _klass->constants();
+  int len = cp->length();
+  GrowableArray<int>* unique_sig_indexes = new GrowableArray<int>(_klass->method_sig_count());
+
+  // Loop through the constant pool looking for each method signature pointed
+  // to by a NameAndType entry.  Save the method signatures' UTF8 constant
+  // pool indexes.
+  for (int index = 1; index < len; index++) {
+    constantTag tag = cp->tag_at(index);
+    if (tag.is_name_and_type()) {
+      const int sig_index = cp->signature_ref_index_at(index);
+      Symbol* const method_sig = cp->symbol_at(sig_index);
+      if (method_sig->char_at(0) == JVM_SIGNATURE_FUNC) {
+        // Multiple constant pool NameAndType entries can point
+        // to the same UTF8 signature so weed out duplicates.
+        unique_sig_indexes->append_if_missing(sig_index);
+      }
+    }
+  }
+
+  for (int i = 0; i < unique_sig_indexes->length(); i++) {
+    const int sig_index = unique_sig_indexes->at(i);
+    Symbol* const method_sig = cp->symbol_at(sig_index);
+
+    // Translate the signature into a growable array of verification types.
+    GrowableArray<VerificationType>* verif_types = new GrowableArray<VerificationType>(10);
+    sig_as_verification_types* sig_verif_types = new sig_as_verification_types(verif_types);
+    translate_signature(method_sig, sig_verif_types, CHECK_VERIFY(this));
+
+    // Add the list of this signature's verification types to the table.
+    bool is_unique = method_sig_table->put(sig_index, sig_verif_types);
+    assert(is_unique, "Duplicate entries in method_signature_table");
+  }
+}
+
 void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
   HandleMark hm(THREAD);
   _method = m;   // initialize _method
   log_info(verification)("Verifying method %s", m->name_and_sig_as_C_string());
 

@@ -2738,42 +2821,17 @@
   // of parsing the signature once to find its size.
   // -3 is for '(', ')' and return descriptor; multiply by 2 is for
   // longs/doubles to be consertive.
   assert(sizeof(VerificationType) == sizeof(uintptr_t),
         "buffer type must match VerificationType size");
-  uintptr_t on_stack_sig_types_buffer[128];
-  // If we make a VerificationType[128] array directly, the compiler calls
-  // to the c-runtime library to do the allocation instead of just
-  // stack allocating it.  Plus it would run constructors.  This shows up
-  // in performance profiles.
 
-  VerificationType* sig_types;
-  int size = (method_sig->utf8_length() - 3) * 2;
-  if (size > 128) {
-    // Long and double occupies two slots here.
-    ArgumentSizeComputer size_it(method_sig);
-    size = size_it.size();
-    sig_types = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, size);
-  } else{
-    sig_types = (VerificationType*)on_stack_sig_types_buffer;
-  }
-  SignatureStream sig_stream(method_sig);
-  int sig_i = 0;
-  while (!sig_stream.at_return_type()) {
-    sig_i += change_sig_to_verificationType(
-      &sig_stream, &sig_types[sig_i], CHECK_VERIFY(this));
-    sig_stream.next();
-  }
-  int nargs = sig_i;
+  // Get the UTF8 index for this signature.
+  int sig_index = cp->signature_ref_index_at(cp->name_and_type_ref_index_at(index));
 
-#ifdef ASSERT
-  {
-    ArgumentSizeComputer size_it(method_sig);
-    assert(nargs == size_it.size(), "Argument sizes do not match");
-    assert(nargs <= (method_sig->utf8_length() - 3) * 2, "estimate of max size isn't conservative enough");
-  }
-#endif
+  // Get the number of arguments for this signature.
+  sig_as_verification_types* mth_sig_verif_types = *(method_signatures_table()->get(sig_index));
+  int nargs = mth_sig_verif_types->num_args();
 
   // Check instruction operands
   u2 bci = bcs->bci();
   if (opcode == Bytecodes::_invokeinterface) {
     address bcp = bcs->bcp();

@@ -2842,14 +2900,20 @@
           "interface method reference is in an indirect superinterface.");
       return;
     }
 
   }
+
+  // Get the verification types for the method's arguments.
+  GrowableArray<VerificationType>* sig_verif_types = mth_sig_verif_types->sig_verif_types();
+  assert(sig_verif_types != NULL, "Missing signature's array of verification types");
   // Match method descriptor with operand stack
+  // The arguments are on the stack in descending order.
   for (int i = nargs - 1; i >= 0; i--) {  // Run backwards
-    current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
+    current_frame->pop_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
   }
+
   // Check objectref on operand stack
   if (opcode != Bytecodes::_invokestatic &&
       opcode != Bytecodes::_invokedynamic) {
     if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
       verify_invoke_init(bcs, index, ref_class_type, current_frame,

@@ -2917,24 +2981,25 @@
         current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
       }
     }
   }
   // Push the result type.
-  if (sig_stream.type() != T_VOID) {
+  int sig_verif_types_len = sig_verif_types->length();
+  if (sig_verif_types_len > nargs) {  // There's a return type
     if (method_name == vmSymbols::object_initializer_name()) {
       // <init> method must have a void return type
       /* Unreachable?  Class file parser verifies that methods with '<' have
        * void return */
       verify_error(ErrorContext::bad_code(bci),
           "Return type must be void in <init> method");
       return;
     }
-    VerificationType return_type[2];
-    int n = change_sig_to_verificationType(
-      &sig_stream, return_type, CHECK_VERIFY(this));
-    for (int i = 0; i < n; i++) {
-      current_frame->push_stack(return_type[i], CHECK_VERIFY(this)); // push types backwards
+
+    assert(sig_verif_types_len <= nargs + 2,
+           "Signature verification types array return type is bogus");
+    for (int i = nargs; i < sig_verif_types_len; i++) {
+      current_frame->push_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
     }
   }
 }
 
 VerificationType ClassVerifier::get_newarray_type(
< prev index next >