--- old/src/hotspot/share/runtime/signature.cpp 2019-03-11 14:27:19.714354138 +0100 +++ new/src/hotspot/share/runtime/signature.cpp 2019-03-11 14:27:19.450354142 +0100 @@ -31,6 +31,7 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "oops/typeArrayKlass.hpp" +#include "oops/valueKlass.hpp" #include "runtime/signature.hpp" // Implementation of SignatureIterator @@ -40,7 +41,7 @@ // Signature = "(" {Parameter} ")" ReturnType. // Parameter = FieldType. // ReturnType = FieldType | "V". -// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType. +// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "Q" ValueClassName ";" | "[" FieldType. // ClassName = string. @@ -89,13 +90,22 @@ if (_parameter_index < 0 ) _return_type = T_OBJECT; size = T_OBJECT_size; break; + case 'Q': + { int begin = ++_index; + Symbol* sig = _signature; + while (sig->char_at(_index++) != ';') ; + do_valuetype(begin, _index); + } + if (_parameter_index < 0 ) _return_type = T_VALUETYPE; + size = T_VALUETYPE_size; + break; case '[': { int begin = ++_index; Symbol* sig = _signature; while (sig->char_at(_index) == '[') { _index++; } - if (sig->char_at(_index) == 'L') { + if (sig->char_at(_index) == 'L' || sig->char_at(_index) == 'Q') { while (sig->char_at(_index++) != ';') ; } else { _index++; @@ -232,6 +242,7 @@ _index++; } break; + case 'Q': case 'L': { while (sig->char_at(_index++) != ';') ; @@ -243,7 +254,7 @@ while (sig->char_at(_index) == '[') { _index++; } - if (sig->char_at(_index) == 'L') { + if (sig->char_at(_index) == 'L' || sig->char_at(_index) == 'Q' ) { while (sig->char_at(_index++) != ';') ; } else { _index++; @@ -307,6 +318,12 @@ while (sig->char_at(_end++) != ';'); break; } + case 'Q': { + _type = T_VALUETYPE; + Symbol* sig = _signature; + while (sig->char_at(_end++) != ';'); + break; + } case '[': { _type = T_ARRAY; Symbol* sig = _signature; @@ -341,7 +358,8 @@ bool SignatureStream::is_object() const { return _type == T_OBJECT - || _type == T_ARRAY; + || _type == T_ARRAY + || _type == T_VALUETYPE; } bool SignatureStream::is_array() const { @@ -353,10 +371,12 @@ int begin = _begin; int end = _end; - if ( _signature->char_at(_begin) == 'L' - && _signature->char_at(_end-1) == ';') { + if (_type == T_OBJECT || _type == T_VALUETYPE) { begin++; end--; + if (begin == end) { + return vmSymbols::java_lang_Object(); + } } // Save names for cleaning up reference count at the end of @@ -384,7 +404,7 @@ return Universe::java_mirror(type()); Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); if (klass == NULL) return NULL; - return klass->java_mirror(); + return _type == T_VALUETYPE ? ValueKlass::cast(InstanceKlass::cast(klass))->value_mirror() : klass->java_mirror(); } Symbol* SignatureStream::as_symbol_or_null() { @@ -394,10 +414,12 @@ int begin = _begin; int end = _end; - if ( _signature->char_at(_begin) == 'L' - && _signature->char_at(_end-1) == ';') { + if (_type == T_OBJECT || _type == T_VALUETYPE) { begin++; end--; + if (begin == end) { + return vmSymbols::java_lang_Object(); + } } char* buffer = NEW_RESOURCE_ARRAY(char, end - begin); @@ -475,6 +497,7 @@ case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 'V': return index + 1; + case 'Q': // fall through case 'L': for (index = index + 1; index < limit; ++index) { char c = type[index]; @@ -499,3 +522,87 @@ return false; } } + +// Adds an argument to the signature +void SigEntry::add_entry(GrowableArray* sig, BasicType bt, int offset) { + sig->append(SigEntry(bt, offset)); + if (bt == T_LONG || bt == T_DOUBLE) { + sig->append(SigEntry(T_VOID, offset)); // Longs and doubles take two stack slots + } +} + +// Inserts a reserved argument at position 'i' +void SigEntry::insert_reserved_entry(GrowableArray* sig, int i, BasicType bt) { + if (bt == T_OBJECT || bt == T_ARRAY || bt == T_VALUETYPE) { + // Treat this as INT to not confuse the GC + bt = T_INT; + } else if (bt == T_LONG || bt == T_DOUBLE) { + // Longs and doubles take two stack slots + sig->insert_before(i, SigEntry(T_VOID, SigEntry::ReservedOffset)); + } + sig->insert_before(i, SigEntry(bt, SigEntry::ReservedOffset)); +} + +// Returns true if the argument at index 'i' is a reserved argument +bool SigEntry::is_reserved_entry(const GrowableArray* sig, int i) { + return sig->at(i)._offset == SigEntry::ReservedOffset; +} + +// Returns true if the argument at index 'i' is not a value type delimiter +bool SigEntry::skip_value_delimiters(const GrowableArray* sig, int i) { + return (sig->at(i)._bt != T_VALUETYPE && + (sig->at(i)._bt != T_VOID || sig->at(i-1)._bt == T_LONG || sig->at(i-1)._bt == T_DOUBLE)); +} + +// Fill basic type array from signature array +int SigEntry::fill_sig_bt(const GrowableArray* sig, BasicType* sig_bt) { + int count = 0; + for (int i = 0; i < sig->length(); i++) { + if (skip_value_delimiters(sig, i)) { + sig_bt[count++] = sig->at(i)._bt; + } + } + return count; +} + +// Create a temporary symbol from the signature array +TempNewSymbol SigEntry::create_symbol(const GrowableArray* sig) { + ResourceMark rm; + int length = sig->length(); + char* sig_str = NEW_RESOURCE_ARRAY(char, 2*length + 3); + int idx = 0; + sig_str[idx++] = '('; + for (int i = 0; i < length; i++) { + BasicType bt = sig->at(i)._bt; + if (bt == T_VALUETYPE || bt == T_VOID) { + // Ignore + } else { + if (bt == T_ARRAY) { + bt = T_OBJECT; // We don't know the element type, treat as Object + } + sig_str[idx++] = type2char(bt); + if (bt == T_OBJECT) { + sig_str[idx++] = ';'; + } + } + } + sig_str[idx++] = ')'; + sig_str[idx++] = '\0'; + return SymbolTable::new_symbol(sig_str, Thread::current()); +} + +// Increment signature iterator (skips value type delimiters and T_VOID) and check if next entry is reserved +bool SigEntry::next_is_reserved(ExtendedSignature& sig, BasicType& bt, bool can_be_void) { + assert(can_be_void || bt != T_VOID, "should never see void"); + if (sig.at_end() || (can_be_void && type2size[bt] == 2 && (*sig)._offset != SigEntry::ReservedOffset)) { + // Don't increment at the end or at a T_LONG/T_DOUBLE which will be followed by a (skipped) T_VOID + return false; + } + assert(bt == T_VOID || type2wfield[bt] == type2wfield[(*sig)._bt], "inconsistent signature"); + ++sig; + if (!sig.at_end() && (*sig)._offset == SigEntry::ReservedOffset) { + bt = (*sig)._bt; + return true; + } + return false; +}