< prev index next >
src/hotspot/share/runtime/signature.cpp
Print this page
*** 29,48 ****
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "runtime/signature.hpp"
// Implementation of SignatureIterator
// Signature syntax:
//
// Signature = "(" {Parameter} ")" ReturnType.
// Parameter = FieldType.
// ReturnType = FieldType | "V".
! // FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
// ClassName = string.
SignatureIterator::SignatureIterator(Symbol* signature) {
_signature = signature;
--- 29,49 ----
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
+ #include "oops/valueKlass.hpp"
#include "runtime/signature.hpp"
// Implementation of SignatureIterator
// Signature syntax:
//
// Signature = "(" {Parameter} ")" ReturnType.
// Parameter = FieldType.
// ReturnType = FieldType | "V".
! // FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "Q" ValueClassName ";" | "[" FieldType.
// ClassName = string.
SignatureIterator::SignatureIterator(Symbol* signature) {
_signature = signature;
*** 87,103 ****
do_object(begin, _index);
}
if (_parameter_index < 0 ) _return_type = T_OBJECT;
size = T_OBJECT_size;
break;
case '[':
{ int begin = ++_index;
Symbol* sig = _signature;
while (sig->char_at(_index) == '[') {
_index++;
}
! if (sig->char_at(_index) == 'L') {
while (sig->char_at(_index++) != ';') ;
} else {
_index++;
}
do_array(begin, _index);
--- 88,113 ----
do_object(begin, _index);
}
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' || sig->char_at(_index) == 'Q') {
while (sig->char_at(_index++) != ';') ;
} else {
_index++;
}
do_array(begin, _index);
*** 230,239 ****
--- 240,250 ----
case 'V':
{
_index++;
}
break;
+ case 'Q':
case 'L':
{
while (sig->char_at(_index++) != ';') ;
}
break;
*** 241,251 ****
{
int begin = ++_index;
while (sig->char_at(_index) == '[') {
_index++;
}
! if (sig->char_at(_index) == 'L') {
while (sig->char_at(_index++) != ';') ;
} else {
_index++;
}
}
--- 252,262 ----
{
int begin = ++_index;
while (sig->char_at(_index) == '[') {
_index++;
}
! if (sig->char_at(_index) == 'L' || sig->char_at(_index) == 'Q' ) {
while (sig->char_at(_index++) != ';') ;
} else {
_index++;
}
}
*** 305,314 ****
--- 316,331 ----
_type = T_OBJECT;
Symbol* sig = _signature;
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;
char c = sig->char_at(_end);
while ('0' <= c && c <= '9') c = sig->char_at(_end++);
*** 339,349 ****
}
bool SignatureStream::is_object() const {
return _type == T_OBJECT
! || _type == T_ARRAY;
}
bool SignatureStream::is_array() const {
return _type == T_ARRAY;
}
--- 356,367 ----
}
bool SignatureStream::is_object() const {
return _type == T_OBJECT
! || _type == T_ARRAY
! || _type == T_VALUETYPE;
}
bool SignatureStream::is_array() const {
return _type == T_ARRAY;
}
*** 351,364 ****
Symbol* SignatureStream::as_symbol(TRAPS) {
// Create a symbol from for string _begin _end
int begin = _begin;
int end = _end;
! if ( _signature->char_at(_begin) == 'L'
! && _signature->char_at(_end-1) == ';') {
begin++;
end--;
}
// Save names for cleaning up reference count at the end of
// SignatureStream scope.
Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
--- 369,384 ----
Symbol* SignatureStream::as_symbol(TRAPS) {
// Create a symbol from for string _begin _end
int begin = _begin;
int end = _end;
! 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
// SignatureStream scope.
Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
*** 382,405 ****
FailureMode failure_mode, TRAPS) {
if (!is_object())
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();
}
Symbol* SignatureStream::as_symbol_or_null() {
// Create a symbol from for string _begin _end
ResourceMark rm;
int begin = _begin;
int end = _end;
! if ( _signature->char_at(_begin) == 'L'
! && _signature->char_at(_end-1) == ';') {
begin++;
end--;
}
char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
for (int index = begin; index < end; index++) {
buffer[index - begin] = _signature->char_at(index);
--- 402,427 ----
FailureMode failure_mode, TRAPS) {
if (!is_object())
return Universe::java_mirror(type());
Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
if (klass == NULL) return NULL;
! return _type == T_VALUETYPE ? ValueKlass::cast(InstanceKlass::cast(klass))->value_mirror() : klass->java_mirror();
}
Symbol* SignatureStream::as_symbol_or_null() {
// Create a symbol from for string _begin _end
ResourceMark rm;
int begin = _begin;
int end = _end;
! 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);
for (int index = begin; index < end; index++) {
buffer[index - begin] = _signature->char_at(index);
*** 473,482 ****
--- 495,505 ----
}
switch (type[index]) {
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];
if (c == ';') {
return index + 1;
*** 497,501 ****
--- 520,608 ----
return true;
default:
return false;
}
}
+
+ // Adds an argument to the signature
+ void SigEntry::add_entry(GrowableArray<SigEntry>* 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<SigEntry>* 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<SigEntry>* 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<SigEntry>* 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<SigEntry>* 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<SigEntry>* 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;
+ }
< prev index next >