< prev index next >

src/hotspot/share/runtime/signature.cpp

Print this page

        

@@ -29,20 +29,21 @@
 #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 ";" | "[" FieldType.
+// FieldType  = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "Q" ValueClassName ";" | "[" FieldType.
 // ClassName  = string.
 
 
 SignatureIterator::SignatureIterator(Symbol* signature) {
   _signature       = signature;

@@ -87,17 +88,26 @@
         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') {
+        if (sig->char_at(_index) == 'L' || sig->char_at(_index) == 'Q') {
           while (sig->char_at(_index++) != ';') ;
         } else {
           _index++;
         }
         do_array(begin, _index);

@@ -230,10 +240,11 @@
       case 'V':
         {
           _index++;
         }
         break;
+      case 'Q':
       case 'L':
         {
           while (sig->char_at(_index++) != ';') ;
         }
         break;

@@ -241,11 +252,11 @@
         {
           int begin = ++_index;
           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++;
           }
         }

@@ -305,10 +316,16 @@
       _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,11 +356,12 @@
 }
 
 
 bool SignatureStream::is_object() const {
   return _type == T_OBJECT
-      || _type == T_ARRAY;
+      || _type == T_ARRAY
+      || _type == T_VALUETYPE;
 }
 
 bool SignatureStream::is_array() const {
   return _type == T_ARRAY;
 }

@@ -351,14 +369,16 @@
 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) == ';') {
+  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,24 +402,26 @@
                                     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();
+  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 (   _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);
   for (int index = begin; index < end; index++) {
     buffer[index - begin] = _signature->char_at(index);

@@ -473,10 +495,11 @@
   }
   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,5 +520,89 @@
       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 >