Hi,

Here are a couple of patches that implement anonymous tuples in method
signatures.  Apologies I haven't got my head around the patch queue,
forest mercurial extensions yet, so these are simple patches generated
from the hotpot/jdk subdirectories.  However, they should be useful if
anyone is interested in reviewing the code.

Known problems:
- I haven't implemented any checking of the class version when
verifying signatures containing tuples.

I'll spend some time getting my head around the patch queue, forest
workflow stuff and look next at implementing tagged tuples in method
signatures.

Mike.
diff -r f500bd7f0376 make/linux/makefiles/gcc.make
--- a/make/linux/makefiles/gcc.make	Sat Apr 16 12:02:54 2011 +0100
+++ b/make/linux/makefiles/gcc.make	Sun Jun 05 14:27:10 2011 +0100
@@ -225,6 +225,8 @@
 DEBUG_CFLAGS += -gstabs
 endif
 
+DEBUG_CFLAGS += -ggdb3
+
 # DEBUG_BINARIES overrides everything, use full -g debug information
 ifeq ($(DEBUG_BINARIES), true)
   DEBUG_CFLAGS = -g
diff -r f500bd7f0376 src/share/vm/classfile/classFileParser.cpp
--- a/src/share/vm/classfile/classFileParser.cpp	Sat Apr 16 12:02:54 2011 +0100
+++ b/src/share/vm/classfile/classFileParser.cpp	Sun Jun 05 14:27:10 2011 +0100
@@ -1615,13 +1615,11 @@
     verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
   }
 
-  int args_size = -1;  // only used when _need_verify is true
-  if (_need_verify) {
-    args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
-                 verify_legal_method_signature(name, signature, CHECK_(nullHandle));
-    if (args_size > MAX_ARGS_SIZE) {
-      classfile_parse_error("Too many arguments in method signature in class file %s", CHECK_(nullHandle));
-    }
+  verify_legal_method_signature(name, signature, CHECK_(nullHandle));
+  ArgumentSizeComputer asc(signature);
+  int args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) + asc.size();
+  if (_need_verify && args_size > MAX_ARGS_SIZE) {
+    classfile_parse_error("Too many arguments in method signature in class file %s", CHECK_(nullHandle));
   }
 
   access_flags.set_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS);
@@ -1940,11 +1938,8 @@
   m->set_result_index(rtf.type());
 #endif
 
-  if (args_size >= 0) {
-    m->set_size_of_parameters(args_size);
-  } else {
-    m->compute_size_of_parameters(THREAD);
-  }
+  m->set_size_of_parameters(args_size);
+
 #ifdef ASSERT
   if (args_size >= 0) {
     m->compute_size_of_parameters(THREAD);
@@ -4351,14 +4346,9 @@
 
 // Checks if signature is a legal method signature.
 // Returns number of parameters
-int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signature, TRAPS) {
-  if (!_need_verify) {
-    // make sure caller's args_size will be less than 0 even for non-static
-    // method so it will be recomputed in compute_size_of_parameters().
-    return -2;
-  }
-
-  unsigned int args_size = 0;
+void ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signature, TRAPS) {
+  if (!_need_verify) { return; }
+
   char buf[fixed_buffer_size];
   char* p = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
   unsigned int length = signature->utf8_length();
@@ -4367,37 +4357,35 @@
   // The first character must be a '('
   if ((length > 0) && (*p++ == JVM_SIGNATURE_FUNC)) {
     length--;
+
     // Skip over legal field signatures
-    nextp = skip_over_field_signature(p, false, length, CHECK_0);
+    nextp = skip_over_field_signature(p, false, length, CHECK);
     while ((length > 0) && (nextp != NULL)) {
-      args_size++;
-      if (p[0] == 'J' || p[0] == 'D') {
-        args_size++;
-      }
       length -= nextp - p;
       p = nextp;
-      nextp = skip_over_field_signature(p, false, length, CHECK_0);
+      nextp = skip_over_field_signature(p, false, length, CHECK);
     }
+
     // The first non-signature thing better be a ')'
     if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) {
       length--;
       if (name->utf8_length() > 0 && name->byte_at(0) == '<') {
         // All internal methods must return void
         if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) {
-          return args_size;
+          return;
         }
       } else {
         // Now we better just have a return value
-        nextp = skip_over_field_signature(p, true, length, CHECK_0);
+        nextp = skip_over_field_signature(p, true, length, CHECK);
         if (nextp && ((int)length == (nextp - p))) {
-          return args_size;
+          return;
         }
       }
     }
   }
   // Report error
-  throwIllegalSignature("Method", name, signature, CHECK_0);
-  return 0;
+  throwIllegalSignature("Method", name, signature, CHECK);
+  return;
 }
 
 
@@ -4579,6 +4567,35 @@
         void_ok = false;
         break;
 
+      case JVM_SIGNATURE_TUPLE:
+        if (TupleSignatures) {
+
+          signature++;
+          length--;
+
+          if (signature[0] == 'V') {
+            signature++;
+            length--;
+
+            while (length > 0 && signature[0] != JVM_SIGNATURE_ENDTUPLE) {
+              char* p = skip_over_field_signature(signature, void_ok, length, CHECK_0);
+
+              if (p == NULL) {
+                return NULL;
+              }
+
+              length -= p - signature;
+              signature = p;
+            }
+
+            if (length > 0 && signature[0] == JVM_SIGNATURE_ENDTUPLE) {
+              return signature + 1;
+            }
+          }
+
+          return NULL;
+        }
+
       default:
         return NULL;
     }
diff -r f500bd7f0376 src/share/vm/classfile/classFileParser.hpp
--- a/src/share/vm/classfile/classFileParser.hpp	Sat Apr 16 12:02:54 2011 +0100
+++ b/src/share/vm/classfile/classFileParser.hpp	Sun Jun 05 14:27:10 2011 +0100
@@ -222,7 +222,7 @@
   void verify_legal_field_name(Symbol* name, TRAPS);
   void verify_legal_method_name(Symbol* name, TRAPS);
   void verify_legal_field_signature(Symbol* fieldname, Symbol* signature, TRAPS);
-  int  verify_legal_method_signature(Symbol* methodname, Symbol* signature, TRAPS);
+  void verify_legal_method_signature(Symbol* methodname, Symbol* signature, TRAPS);
   void verify_legal_class_modifiers(jint flags, TRAPS);
   void verify_legal_field_modifiers(jint flags, bool is_interface, TRAPS);
   void verify_legal_method_modifiers(jint flags, bool is_interface, Symbol* name, TRAPS);
diff -r f500bd7f0376 src/share/vm/prims/jvm.h
--- a/src/share/vm/prims/jvm.h	Sat Apr 16 12:02:54 2011 +0100
+++ b/src/share/vm/prims/jvm.h	Sun Jun 05 14:27:10 2011 +0100
@@ -1111,6 +1111,8 @@
 #define JVM_SIGNATURE_SHORT             'S'
 #define JVM_SIGNATURE_VOID              'V'
 #define JVM_SIGNATURE_BOOLEAN           'Z'
+#define JVM_SIGNATURE_TUPLE             '{'
+#define JVM_SIGNATURE_ENDTUPLE          '}'
 
 /*
  * A function defined by the byte-code verifier and called by the VM.
diff -r f500bd7f0376 src/share/vm/runtime/globals.hpp
--- a/src/share/vm/runtime/globals.hpp	Sat Apr 16 12:02:54 2011 +0100
+++ b/src/share/vm/runtime/globals.hpp	Sun Jun 05 14:27:10 2011 +0100
@@ -3772,6 +3772,9 @@
   product(uintx, StringTableSize, 1009,                                     \
           "Number of buckets in the interned String table")                 \
                                                                             \
+  product(bool, TupleSignatures, false,                                     \
+          "Enable Tuple Signatures")                                        \
+                                                                            \
   product(bool, UseVMInterruptibleIO, false,                                \
           "(Unstable, Solaris-specific) Thread interrupt before or with "   \
           "EINTR for I/O operations results in OS_INTRPT. The default value"\
diff -r f500bd7f0376 src/share/vm/runtime/signature.cpp
--- a/src/share/vm/runtime/signature.cpp	Sat Apr 16 12:02:54 2011 +0100
+++ b/src/share/vm/runtime/signature.cpp	Sun Jun 05 14:27:10 2011 +0100
@@ -40,7 +40,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 ";" | "[" FieldType | "{V" FieldType* "}".
 // ClassName  = string.
 
 
@@ -115,6 +115,18 @@
       }
       size = T_ARRAY_size;
       break;
+    case '{':
+      if (TupleSignatures) {
+        _index += 2; // Skip 'V' tag
+        size = T_VOID_size;
+        break;
+      }
+    case '}':
+      if (TupleSignatures) {
+        _index++;
+        size = T_VOID_size;
+        break;
+      }
     default:
       ShouldNotReachHere();
       break;
@@ -304,6 +316,15 @@
       break;
     }
     case ')': _end++; next(); _at_return_type = true; break;
+    case '{':
+      if (TupleSignatures) {
+        _end += 2; // Skip 'V' tag
+        next(); break;
+      }
+    case '}':
+      if (TupleSignatures) {
+        _end++; next(); break;
+      }
     default : ShouldNotReachHere();
   }
 }
@@ -445,7 +466,30 @@
           return -1;
         }
       }
-      // fall through
+      return -1; // Not valid
+
+    case '{':
+      if (!TupleSignatures) {
+        return -1;
+      }
+
+      ++index;
+      if (index < limit && type[index] == 'V') {
+        for (index = index + 1; index < limit;) {
+          if (type[index] == '}') {
+            return index + 1;
+          }
+
+          ssize_t sub_index = is_valid_type(&type[index], limit - index);
+          if (-1 == sub_index) {
+            return -1;
+          }
+
+          index += sub_index;
+        }
+      }
+      return -1; // Not valid
+
     default: ; // fall through
   }
   return -1;
diff -r f500bd7f0376 test/runtime/6804523/ClassTransformer.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/6804523/ClassTransformer.java	Sun Jun 05 14:27:10 2011 +0100
@@ -0,0 +1,109 @@
+import static java.lang.System.arraycopy;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+
+
+public class ClassTransformer
+{
+    private final String filename;
+    private byte[] classFile;
+    
+    public ClassTransformer(String filename, byte[] classFile)
+    {
+        this.filename = filename;
+        this.classFile = classFile;
+    }
+
+    public void transform(String from, String to) throws UnsupportedEncodingException
+    {
+        byte[] fromPattern = getBytePattern(from);
+        SimpleBoyerMoore sbm = new SimpleBoyerMoore(fromPattern);
+        
+        int index = sbm.patternSearch(classFile, 0, classFile.length);
+        
+        if (index != SimpleBoyerMoore.PATTERN_NOT_FOUND)
+        {
+            byte[] toPattern = getBytePattern(to);
+            
+            int length = classFile.length + (toPattern.length - fromPattern.length);
+            byte[] newClassFile = new byte[length];
+            
+            System.arraycopy(classFile, 0, newClassFile, 0, index);
+            System.arraycopy(toPattern, 0, newClassFile, index, toPattern.length);
+            System.arraycopy(classFile, index + fromPattern.length, 
+                             newClassFile, index + toPattern.length, classFile.length - (index + fromPattern.length));
+            
+            classFile = newClassFile;
+            
+            System.out.printf("Transformed %s to %s in file: %s%n", from, to, filename);
+        }
+    }
+
+    public byte[] getBytePattern(String from)
+    {
+        byte[] fromPattern = from.getBytes();
+        short length = (short)fromPattern.length;
+        byte[] fromPatternWithLength = new byte[2 + length];
+        arraycopy(fromPattern, 0, fromPatternWithLength, 2, length);
+
+        fromPatternWithLength[0] = (byte) (length >>> 8);
+        fromPatternWithLength[1] = (byte) (length);
+        
+        return fromPatternWithLength;
+    }
+    
+    public void store(String filename) throws IOException
+    {
+        FileOutputStream stream = new FileOutputStream(filename);
+        stream.write(classFile);
+    }
+
+    public static ClassTransformer load(String filename) throws IOException
+    {
+        RandomAccessFile raf = new RandomAccessFile(new File(filename), "r");
+        byte[] classFile = new byte[(int) raf.length()];
+        raf.readFully(classFile);
+        return new ClassTransformer(filename, classFile);
+    }
+    
+    public static void main(String[] args) throws Exception
+    {
+        if (args.length == 0)
+        {
+            throw new RuntimeException("Usage ClassTransformer <files...>");
+        }
+        
+        for (String arg : args)
+        {
+            doTransform(arg);            
+        }
+    }
+
+    public static void doTransform(String filename) throws IOException, UnsupportedEncodingException
+    {
+        ClassTransformer transformer = ClassTransformer.load(filename);
+        applySignatures(transformer);
+        transformer.store(filename);
+    }
+
+    public static void applySignatures(ClassTransformer transformer) throws UnsupportedEncodingException
+    {
+        transformer.transform("(Z)I", "({VZ})I");
+        transformer.transform("(C)I", "({VC})I");
+        transformer.transform("(S)I", "({VS})I");
+        transformer.transform("(I)I", "({VI})I");
+        transformer.transform("(F)F", "({VF})F");
+        transformer.transform("(D)D", "({VD})D");
+        transformer.transform("([I)I", "({V[I})I");
+        transformer.transform("(J)J", "({VJ})J");
+        transformer.transform("(II)I", "({VII})I");
+        transformer.transform("(IIII)I", "({VII}{VII})I");
+        transformer.transform("(Ljava/lang/String;)I", "({VLjava/lang/String;})I");
+        transformer.transform("([Ljava/lang/String;)I", "({V[Ljava/lang/String;})I");
+        transformer.transform("(I[Ljava/lang/String;)I", "({VI[Ljava/lang/String;})I");
+    }
+}
diff -r f500bd7f0376 test/runtime/6804523/SimpleBoyerMoore.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/6804523/SimpleBoyerMoore.java	Sun Jun 05 14:27:10 2011 +0100
@@ -0,0 +1,114 @@
+
+
+/*
+ * Bunisoft the Open Source Communications Company
+ * Copyright 2006, Bunisoft Inc.,
+ *
+ * Portions of this software are Copyright 2006, JBoss Inc., and 
+ * individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a full listing of
+ * individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+/**
+ * <code>SimpleBoyerMoore</code> is an implementation of the simplified
+ * version of the Boyer-Moore pattern search algorithm. This just means that the
+ * "good match" portion of the algorithm is removed, which improves the
+ * performance of non repeating patterns with the obvious side-effect of
+ * reducing repeating pattern performance (e.g. gaggaggaaaggaggaagagaggaga).
+ * 
+ * This version of the algorithm performs incredibly well if the pattern is
+ * rare, for example a MIME boundary.
+ * 
+ * This algorithm is binary safe.
+ * 
+ * @author <a href="mailto:[email protected]">Jason T. Greene</a>
+ */
+public class SimpleBoyerMoore
+{
+    private final int[] badMatch = new int[256];
+    private final byte[] pattern;
+    public static final int PATTERN_NOT_FOUND = -1;
+
+    /**
+     * Constructs a <code>SimpleBoyerMoore</code> instance. This internally
+     * stores the pattern so that the same instance can be used across several
+     * searches.
+     * 
+     * @param pattern
+     *            the pattern to search for
+     */
+    public SimpleBoyerMoore(byte[] pattern)
+    {
+        this.pattern = pattern;
+        precomputeBadMatchTable();
+    }
+
+    private void precomputeBadMatchTable()
+    {
+        java.util.Arrays.fill(badMatch, pattern.length);
+        for (int i = 0; i < pattern.length - 1; i++)
+        {
+            badMatch[pattern[i] & 0xff] = pattern.length - i - 1;
+        }
+    }
+
+    /**
+     * Find an occurence of the search pattern within text.
+     * 
+     * @param text
+     *            a byte array of data to seach
+     * @param offset
+     *            the index in text to start searching from
+     * @param length
+     *            the maximum number of bytes to search
+     * 
+     * @return if a match is found, the index of text where the patter occurs,
+     *         otherwise {@link #PATTERN_NOT_FOUND}
+     */
+    public int patternSearch(byte[] text, int offset, int length)
+    {
+        if (pattern.length > length)
+        {
+            return PATTERN_NOT_FOUND;
+        }
+
+        int i = 0, j = 0, k = 0;
+        int end = offset + length;
+
+        for (i = offset + pattern.length - 1; i < end; i += badMatch[text[i] & 0xff])
+        {
+            for (j = pattern.length - 1, k = i; (j >= 0) && (text[k] == pattern[j]); j--)
+            {
+                k--;
+            }
+            if (j == -1)
+            {
+                return k + 1;
+            }
+        }
+
+        return PATTERN_NOT_FOUND;
+    }
+
+    public int length()
+    {
+        return pattern.length;
+    }
+}
\ No newline at end of file
diff -r f500bd7f0376 test/runtime/6804523/Test6804523.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/6804523/Test6804523.sh	Sun Jun 05 14:27:10 2011 +0100
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+LOCATION=`dirname $0`
+
+if [ "$TEST_JAVA_HOME" == "" ]
+then
+	TEST_JAVA_HOME=$LOCATION/../../../../build/linux-i586-debug/bin
+fi
+
+rm -f $LOCATION/*.class
+
+echo "Compiling..."
+$TEST_JAVA_HOME/javac -d $LOCATION $LOCATION/*.java
+
+echo "Transforming..."
+$TEST_JAVA_HOME/java -cp $LOCATION ClassTransformer $LOCATION/TupleSignature.class $LOCATION/TestTupleSignature.class
+
+echo "Running..."
+$TEST_JAVA_HOME/java -XX:+TupleSignatures TestTupleSignature
diff -r f500bd7f0376 test/runtime/6804523/TestTupleSignature.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/6804523/TestTupleSignature.java	Sun Jun 05 14:27:10 2011 +0100
@@ -0,0 +1,23 @@
+public class TestTupleSignature {
+	
+	public static void main(String[] args) {
+		System.out.printf("{VZ}  : %s%n",     1 == TupleSignature.staticVZ(true));
+		System.out.printf("{VB}  : %s%n",    67 == TupleSignature.staticVB((byte) 67));
+		System.out.printf("{VC}  : %s%n",   'm' == TupleSignature.staticVC('m'));
+		System.out.printf("{VS}  : %s%n",   345 == TupleSignature.staticVS((short) 345));
+		System.out.printf("{VI}  : %s%n", 70000 == TupleSignature.staticVI(70000));
+		System.out.printf("{VF}  : %s%n", 0.32F == TupleSignature.staticVF(0.32F));
+		System.out.printf("{VD}  : %s%n", 0.64D == TupleSignature.staticVD(0.64D));
+		System.out.printf("{V[I} : %s%n",   534 == TupleSignature.staticVArray(new int[]{ 534 }));
+		System.out.printf("{VJ}  : %s%n", 1000000000L == TupleSignature.staticVJ(1000000000L));
+		System.out.printf("{VII} : %s%n", 72701 == TupleSignature.staticVII(70000, 2701));
+		System.out.printf("{VI[I}: %s%n",  2702 == TupleSignature.staticVIArray(2701, new int[] { 1 }));
+		System.out.printf("{VII} : %s%n", 72701 == new TupleSignature().instanceVII(70000, 2701));
+		System.out.printf("{VII}{VII}: %s%n", 72792 == TupleSignature.staticVIIVII(70000, 2701, 1, 90));
+		System.out.printf("{VI{VII}} : %s%n", 72702 == TupleSignature.staticVInVII(70000, 2701, 1));
+		System.out.printf("{VLjava/lang/String;}  : %s%n", "foo".hashCode() == TupleSignature.staticVL("foo"));
+		System.out.printf("{V[Ljava/lang/String;} : %s%n", "bar".hashCode() == TupleSignature.staticVLArray(new String[] {"bar"}));
+		System.out.printf("{VI[Ljava/lang/String;}: %s%n", 2701 + "foo".hashCode() == TupleSignature.staticVIL(2701, "foo"));
+	}
+	
+}
\ No newline at end of file
diff -r f500bd7f0376 test/runtime/6804523/TupleSignature.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/6804523/TupleSignature.java	Sun Jun 05 14:27:10 2011 +0100
@@ -0,0 +1,70 @@
+public class TupleSignature {
+	
+	public static int staticVZ(boolean b) {
+		return b ? 1 : 0;
+	}
+	
+	public static int staticVB(byte b) {
+		return (int) b;
+	}
+	
+	public static int staticVC(char c) {
+		return c;
+	}
+	
+	public static int staticVS(short s) {
+		return s;
+	}
+	
+	public static int staticVI(int i) {
+		return i;
+	}
+	
+	public static long staticVJ(long l) {
+		return l;
+	}
+	
+	public static float staticVF(float f) {
+		return f;
+	}
+	
+	public static double staticVD(double d) {
+		return d;
+	}
+	
+	public static int staticVArray(int[] is) {
+		return is[0];
+	}
+	
+	public static int staticVL(String s) {
+		return s.hashCode();
+	}
+	
+	public static int staticVLArray(String[] ss) {
+		return ss[0].hashCode();
+	}
+	
+	public static int staticVII(int i, int j) {
+		return i + j;
+	}
+
+	public static int staticVInVII(int i, int j, int k) {
+		return i + j + k;
+	}
+
+	public static int staticVIIVII(int i, int j, int k, int l) {
+		return i + j + k + l;
+	}
+
+	public static int staticVIL(int i, String s) {
+		return i + s.hashCode();
+	}
+
+	public static int staticVIArray(int i, int[] is) {
+		return i + is[0];
+	}
+
+	public int instanceVII(int i, int j) {
+		return i + j;
+	}
+}
\ No newline at end of file
diff -r 74f351de24b5 src/share/native/common/check_code.c
--- a/src/share/native/common/check_code.c	Sat Apr 16 12:02:55 2011 +0100
+++ b/src/share/native/common/check_code.c	Sun Jun 05 14:27:37 2011 +0100
@@ -426,6 +426,7 @@
 static void pop_and_free(context_type *context);
 
 static int signature_to_args_size(const char *method_signature);
+static const char* erase_signature(context_type* context, const char* signature);
 
 #ifdef DEBUG
 static void print_stack (context_type *, stack_info_type *stack_info);
@@ -882,7 +883,6 @@
     context->field_index = -1;
 }
 
-
 /**
  * We read all of the class's methods' code because it is possible that
  * the verification of one method could resulting in linking further
@@ -1711,7 +1711,6 @@
         CCerror(context, "Illegal type in constant pool");
 }
 
-
 static void
 initialize_dataflow(context_type *context)
 {
@@ -1750,10 +1749,14 @@
             *reg_ptr++ = context->currentclass_info;
         }
     }
+
     signature = JVM_GetMethodIxSignatureUTF(env, cb, mi);
     check_and_push(context, signature, VM_STRING_UTF);
+    const char* erased_signature = erase_signature(context, signature);
+    check_and_push(context, erased_signature, VM_MALLOC_BLK);
+
     /* Fill in each of the arguments into the registers. */
-    for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) {
+    for (p = erased_signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) {
         char fieldchar = signature_to_fieldtype(context, &p, &full_info);
         switch (fieldchar) {
             case 'D': case 'L':
@@ -1773,6 +1776,7 @@
         context->return_type = full_info;
     }
     pop_and_free(context);
+    pop_and_free(context);
     /* Indicate that we need to look at the first instruction. */
     idata[0].changed = JNI_TRUE;
 }
@@ -1995,6 +1999,9 @@
                                            operand);
             char *ip = buffer;
             check_and_push(context, signature, VM_STRING_UTF);
+            const char* erased_signature = erase_signature(context, signature);
+            check_and_push(context, erased_signature, VM_MALLOC_BLK);
+
 #ifdef DEBUG
             if (verify_verbose) {
                 print_formatted_fieldname(context, operand);
@@ -2002,10 +2009,11 @@
 #endif
             if (opcode == JVM_OPC_putfield)
                 *ip++ = 'A';    /* object for putfield */
-            *ip++ = signature_to_fieldtype(context, &signature, &put_full_info);
+            *ip++ = signature_to_fieldtype(context, &erased_signature, &put_full_info);
             *ip = '\0';
             stack_operands = buffer;
             pop_and_free(context);
+            pop_and_free(context);
             break;
         }
 
@@ -2022,6 +2030,9 @@
             char *ip = buffer;
             const char *p;
             check_and_push(context, signature, VM_STRING_UTF);
+            const char* erased_signature = erase_signature(context, signature);
+            check_and_push(context, erased_signature, VM_MALLOC_BLK);
+
 #ifdef DEBUG
             if (verify_verbose) {
                 print_formatted_methodname(context, operand);
@@ -2031,7 +2042,7 @@
                 opcode != JVM_OPC_invokedynamic)
                 /* First, push the object */
                 *ip++ = (opcode == JVM_OPC_invokeinit ? '@' : 'A');
-            for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) {
+            for (p = erased_signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) {
                 *ip++ = signature_to_fieldtype(context, &p, &full_info);
                 if (ip >= buffer + sizeof(buffer) - 1)
                     CCerror(context, "Signature %s has too many arguments",
@@ -2039,7 +2050,8 @@
             }
             *ip = 0;
             stack_operands = buffer;
-            pop_and_free(context);
+            pop_and_free(context); // erased_signature
+            pop_and_free(context); // signature
             break;
         }
 
@@ -2323,6 +2335,9 @@
             int item;
             const char *p;
             check_and_push(context, signature, VM_STRING_UTF);
+            const char* erased_signature = erase_signature(context, signature);
+            check_and_push(context, erased_signature, VM_MALLOC_BLK);
+
             if (opcode == JVM_OPC_invokestatic ||
                 opcode == JVM_OPC_invokedynamic) {
                 item = 0;
@@ -2392,7 +2407,7 @@
                 }
                 item = 1;
             }
-            for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; item++)
+            for (p = erased_signature + 1; *p != JVM_SIGNATURE_ENDFUNC; item++)
                 if (signature_to_fieldtype(context, &p, &full_info) == 'A') {
                     if (!isAssignableTo(context,
                                         stack_extra_info[item], full_info)) {
@@ -2400,7 +2415,8 @@
                     }
                 }
 
-            pop_and_free(context);
+            pop_and_free(context); // erased_signature
+            pop_and_free(context); // signature
             break;
         }
 
@@ -2730,7 +2746,10 @@
                                                                 operand);
             const char *result_signature;
             check_and_push(context, signature, VM_STRING_UTF);
-            result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC);
+            const char* erased_signature = erase_signature(context, signature);
+            check_and_push(context, erased_signature, VM_MALLOC_BLK);
+
+            result_signature = strchr(erased_signature, JVM_SIGNATURE_ENDFUNC);
             if (result_signature++ == NULL) {
                 CCerror(context, "Illegal signature %s", signature);
             }
@@ -2742,7 +2761,8 @@
                 buffer[1] = '\0';
                 stack_results = buffer;
             }
-            pop_and_free(context);
+            pop_and_free(context); // erased_signature
+            pop_and_free(context); // signature
             break;
         }
 
@@ -3538,7 +3558,8 @@
     return p;
 }
 
-/* Get the class associated with a particular field or method or class in the
+/* Get the class associated   printf("Count: %d\n", count);
+ * with a particular field or method or class in the
  * constant pool.  If is_field is true, we've got a field or method.  If
  * false, we've got a class.
  */
@@ -3570,13 +3591,17 @@
     }
 
     check_and_push(context, classname, VM_STRING_UTF);
+    const char* erased_classname = erase_signature(context, classname);
+    check_and_push(context, erased_classname, VM_MALLOC_BLK);
+
     if (classname[0] == JVM_SIGNATURE_ARRAY) {
         /* This make recursively call us, in case of a class array */
-        signature_to_fieldtype(context, &classname, &result);
+        signature_to_fieldtype(context, &erased_classname, &result);
     } else {
         result = make_class_info_from_name(context, classname);
     }
-    pop_and_free(context);
+    pop_and_free(context); // erased_signature
+    pop_and_free(context); // signature
     return result;
 }
 
@@ -3709,6 +3734,11 @@
                 result = 'L';
                 break;
 
+            case '{':
+            case 'V':
+            case '}':
+                continue;
+
             case JVM_SIGNATURE_ARRAY:
                 array_depth++;
                 continue;       /* only time we ever do the loop > 1 */
@@ -4121,6 +4151,89 @@
     return args_size;
 }
 
+static const char* erase_signature(context_type *context, const char* signature)
+{
+    char* erased;
+    char* p;
+    char* e;
+
+    int count = 0;
+    int isParameter = 0;
+
+    for (p = signature; *p; p++)
+    {
+        switch (*p)
+        {
+          case 'V'   :
+            if (!isParameter) {
+              count++;
+            }
+            break;
+
+          case '{' :
+          case '}' :
+            break;
+
+          case '(' :
+            isParameter++;
+            count++;
+            break;
+
+          case ')' :
+            isParameter--;
+            count++;
+            break;
+
+          default:
+            count++;
+        }
+    }
+
+    isParameter = 0;
+
+    erased = (char*) malloc(sizeof(char) * (count + 1));
+    if (erased == 0) {
+        CCout_of_memory(context);
+    }
+
+    for (p = signature, e = erased; *p; p++)
+    {
+        switch (*p)
+        {
+        case 'V'   :
+          if (!isParameter)
+          {
+            *e = *p;
+            e++;
+          }
+          break;
+
+        case '}' :
+        case '{' :
+          break;
+
+        case '(' :
+          isParameter++;
+          *e = *p;
+          e++;
+          break;
+
+        case ')' :
+          isParameter--;
+          *e = *p;
+          e++;
+          break;
+
+        default:
+          *e = *p;
+          e++;
+        }
+    }
+
+    return erased;
+}
+
+
 #ifdef DEBUG
 
 /* Below are for debugging. */
_______________________________________________
mlvm-dev mailing list
[email protected]
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to