< prev index next >

src/hotspot/share/classfile/verifier.cpp

Print this page

        

*** 572,582 **** // Methods in ClassVerifier ClassVerifier::ClassVerifier( InstanceKlass* klass, TRAPS) : _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL), ! _message(NULL), _klass(klass) { _this_type = VerificationType::reference_type(klass->name()); } ClassVerifier::~ClassVerifier() { // Decrement the reference count for any symbols created. --- 572,582 ---- // Methods in ClassVerifier ClassVerifier::ClassVerifier( InstanceKlass* klass, TRAPS) : _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL), ! _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,608 **** --- 599,616 ---- } 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,632 **** --- 631,715 ---- 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,2779 **** // 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; ! #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 // Check instruction operands u2 bci = bcs->bci(); if (opcode == Bytecodes::_invokeinterface) { address bcp = bcs->bcp(); --- 2821,2837 ---- // 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"); ! // Get the UTF8 index for this signature. ! int sig_index = cp->signature_ref_index_at(cp->name_and_type_ref_index_at(index)); ! // 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,2855 **** "interface method reference is in an indirect superinterface."); return; } } // Match method descriptor with operand stack for (int i = nargs - 1; i >= 0; i--) { // Run backwards ! current_frame->pop_stack(sig_types[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, --- 2900,2919 ---- "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_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,2940 **** current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this)); } } } // Push the result type. ! if (sig_stream.type() != T_VOID) { 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 } } } VerificationType ClassVerifier::get_newarray_type( --- 2981,3005 ---- current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this)); } } } // Push the result type. ! 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; } ! ! 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 >