< prev index next >
src/hotspot/share/classfile/verifier.cpp
Print this page
rev 54022 : 8220366: Optimize Symbol handling in ClassVerifier and SignatureStream
Reviewed-by: TBD
@@ -162,58 +162,59 @@
PerfClassTraceTime::CLASS_VERIFY);
// 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.
-
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);
- char* exception_message = message_buffer;
+ char* message_buffer = NULL;
+ char* exception_message = NULL;
- const char* klassName = klass->external_name();
bool can_failover = FailOverToOldVerifier &&
klass->major_version() < NOFAILOVER_MAJOR_VERSION;
- log_info(class, init)("Start class verification for: %s", klassName);
+ log_info(class, init)("Start class verification for: %s", klass->external_name());
if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
ClassVerifier split_verifier(klass, THREAD);
split_verifier.verify_class(THREAD);
exception_name = split_verifier.result();
if (can_failover && !HAS_PENDING_EXCEPTION &&
(exception_name == vmSymbols::java_lang_VerifyError() ||
exception_name == vmSymbols::java_lang_ClassFormatError())) {
- log_info(verification)("Fail over class verification to old verifier for: %s", klassName);
- log_info(class, init)("Fail over class verification to old verifier for: %s", klassName);
+ log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
+ log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
+ message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
+ exception_message = message_buffer;
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
}
if (exception_name != NULL) {
exception_message = split_verifier.exception_message();
}
} else {
+ message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
+ exception_message = message_buffer;
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
}
LogTarget(Info, class, init) lt1;
if (lt1.is_enabled()) {
LogStream ls(lt1);
- log_end_verification(&ls, klassName, exception_name, THREAD);
+ log_end_verification(&ls, klass->external_name(), exception_name, THREAD);
}
LogTarget(Info, verification) lt2;
if (lt2.is_enabled()) {
LogStream ls(lt2);
- log_end_verification(&ls, klassName, exception_name, THREAD);
+ log_end_verification(&ls, klass->external_name(), exception_name, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
return false; // use the existing exception
} else if (exception_name == NULL) {
- return true; // verifcation succeeded
+ return true; // verification succeeded
} else { // VerifyError or ClassFormatError to be created and thrown
- ResourceMark rm(THREAD);
Klass* kls =
SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false);
if (log_is_enabled(Debug, class, resolve)) {
Verifier::trace_class_resolution(kls, klass);
}
@@ -226,11 +227,14 @@
// So bail out here by throwing the preallocated VM error.
THROW_OOP_(Universe::virtual_machine_error_instance(), false);
}
kls = kls->super();
}
+ if (message_buffer != NULL) {
message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
+ }
+ assert(exception_message != NULL, "");
THROW_MSG_(exception_name, exception_message, false);
}
}
bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_verify_class) {
@@ -567,22 +571,23 @@
// Methods in ClassVerifier
ClassVerifier::ClassVerifier(
InstanceKlass* klass, TRAPS)
- : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) {
+ : _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL),
+ _message(NULL), _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.
+ if (_symbols != NULL) {
for (int i = 0; i < _symbols->length(); i++) {
Symbol* s = _symbols->at(i);
s->decrement_refcount();
}
+ }
}
VerificationType ClassVerifier::object_type() const {
return VerificationType::reference_type(vmSymbols::java_lang_Object());
}
@@ -3100,15 +3105,38 @@
// 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);
+ const char* name = (const char*)s->base() + begin;
+ int length = end - begin;
+
+ // Quick deduplication check
+ if (_previous_symbol != NULL && _previous_symbol->equals(name, length)) {
+ return _previous_symbol;
+ }
+ Symbol* sym = SymbolTable::new_symbol(name, length, CHECK_NULL);
+ if (!sym->is_permanent()) {
+ if (_symbols == NULL) {
+ _symbols = new GrowableArray<Symbol*>(50, 0, NULL);
+ }
_symbols->push(sym);
+ }
+ _previous_symbol = sym;
return sym;
}
-Symbol* ClassVerifier::create_temporary_symbol(const char *s, int length, TRAPS) {
- Symbol* sym = SymbolTable::new_symbol(s, length, CHECK_NULL);
+Symbol* ClassVerifier::create_temporary_symbol(const char *name, int length, TRAPS) {
+ // Quick deduplication check
+ if (_previous_symbol != NULL && _previous_symbol->equals(name, length)) {
+ return _previous_symbol;
+ }
+ Symbol* sym = SymbolTable::new_symbol(name, length, CHECK_NULL);
+ if (!sym->is_permanent()) {
+ if (_symbols == NULL) {
+ _symbols = new GrowableArray<Symbol*>(50, 0, NULL);
+ }
_symbols->push(sym);
+ }
+ _previous_symbol = sym;
return sym;
}
< prev index next >