Hi,

Attached are my latests TupleSignature patches.  This starts to add
support for tagged tuples in method calls.  It's very basic right now,
the classes load and methods can be called.  There are a couple of
outstanding issues:

- No support for validating the class used as the "tag".  There should
a check it exists and that the field format matches the arguments on
the tuple.
- No updates for the JDK verifier, so to run it you'll need
-Xverify:none to run it.

Mike.
User Id: mikeb2701
diff -r b9a96402be9a series
--- a/series	Tue Jul 12 12:29:05 2011 -0700
+++ b/series	Sun Jul 17 13:16:27 2011 +0100
@@ -30,3 +30,4 @@
 coro-standalone.patch   #+/meth #-/coro
 coro-meth.patch         #-/meth #-/coro #+9f82eb2ae02c
 coro.patch    	        #-/coro #+9f82eb2ae02c
+tsigs.patch #+testable
diff -r b9a96402be9a tsigs.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tsigs.patch	Sun Jul 17 13:16:27 2011 +0100
@@ -0,0 +1,737 @@
+diff -r b0ff3165cd05 make/linux/makefiles/gcc.make
+--- a/make/linux/makefiles/gcc.make	Sat Jul 16 13:06:16 2011 +0100
++++ b/make/linux/makefiles/gcc.make	Sun Jul 17 13:13:57 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 b0ff3165cd05 src/share/vm/classfile/classFileParser.cpp
+--- a/src/share/vm/classfile/classFileParser.cpp	Sat Jul 16 13:06:16 2011 +0100
++++ b/src/share/vm/classfile/classFileParser.cpp	Sun Jul 17 13:13:57 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);
+@@ -4353,14 +4348,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();
+@@ -4369,37 +4359,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;
+ }
+ 
+ 
+@@ -4545,26 +4533,10 @@
+       case JVM_SIGNATURE_DOUBLE:
+         return signature + 1;
+       case JVM_SIGNATURE_CLASS: {
+-        if (_major_version < JAVA_1_5_VERSION) {
+-          // Skip over the class name if one is there
+-          char* p = skip_over_field_name(signature + 1, true, --length);
+-
+-          // The next character better be a semicolon
+-          if (p && (p - signature) > 1 && p[0] == ';') {
+-            return p + 1;
+-          }
+-        } else {
+-          // 4900761: For class version > 48, any unicode is allowed in class name.
+-          length--;
+-          signature++;
+-          while (length > 0 && signature[0] != ';') {
+-            if (signature[0] == '.') {
+-              classfile_parse_error("Class name contains illegal character '.' in descriptor in class file %s", CHECK_0);
+-            }
+-            length--;
+-            signature++;
+-          }
+-          if (signature[0] == ';') { return signature + 1; }
++        char* p = skip_over_class_name(signature, length, CHECK_0);
++
++        if (p) {
++          return p;
+         }
+ 
+         return NULL;
+@@ -4581,9 +4553,81 @@
+         void_ok = false;
+         break;
+ 
++      case JVM_SIGNATURE_TUPLE:
++        if (TupleSignatures) {
++
++          signature++;
++          length--;
++
++          // Anonymous Tuple
++          if (signature[0] == 'V') {
++            signature++;
++            length--;
++          // Tagged Tuple contain a class name
++          } else if (signature[0] == JVM_SIGNATURE_CLASS) {
++            char* p = skip_over_class_name(signature, length, CHECK_0);
++
++            if (p == NULL) {
++              return NULL;
++            }
++
++            length -= p - signature;
++            signature = p;
++
++          } else {
++            return NULL;
++          }
++
++          // Signature of the types used by the tuple
++          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;
+     }
+   }
+   return NULL;
+ }
++
++char* ClassFileParser::skip_over_class_name(char* signature, unsigned int length, TRAPS) {
++  if (_major_version < JAVA_1_5_VERSION) {
++    // Skip over the class name if one is there
++    char* p = skip_over_field_name(signature + 1, true, --length);
++
++    // The next character better be a semicolon
++    if (p && (p - signature) > 1 && p[0] == ';') {
++      return p + 1;
++    }
++  } else {
++    // 4900761: For class version > 48, any unicode is allowed in class name.
++    length--;
++    signature++;
++    while (length > 0 && signature[0] != ';') {
++      if (signature[0] == '.') {
++        classfile_parse_error("Class name contains illegal character '.' in descriptor in class file %s", CHECK_0);
++      }
++      length--;
++      signature++;
++    }
++    if (signature[0] == ';') { return signature + 1; }
++  }
++
++  return NULL;
++}
++
++
+diff -r b0ff3165cd05 src/share/vm/classfile/classFileParser.hpp
+--- a/src/share/vm/classfile/classFileParser.hpp	Sat Jul 16 13:06:16 2011 +0100
++++ b/src/share/vm/classfile/classFileParser.hpp	Sun Jul 17 13:13:57 2011 +0100
+@@ -222,13 +222,14 @@
+   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);
+   bool verify_unqualified_name(char* name, unsigned int length, int type);
+   char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
+   char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
++  char* skip_over_class_name(char* signature, unsigned int length, TRAPS);
+ 
+   bool is_anonymous() {
+     assert(EnableInvokeDynamic || _host_klass.is_null(), "");
+diff -r b0ff3165cd05 src/share/vm/prims/jvm.h
+--- a/src/share/vm/prims/jvm.h	Sat Jul 16 13:06:16 2011 +0100
++++ b/src/share/vm/prims/jvm.h	Sun Jul 17 13:13:57 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 b0ff3165cd05 src/share/vm/runtime/globals.hpp
+--- a/src/share/vm/runtime/globals.hpp	Sat Jul 16 13:06:16 2011 +0100
++++ b/src/share/vm/runtime/globals.hpp	Sun Jul 17 13:13:57 2011 +0100
+@@ -3791,6 +3791,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 b0ff3165cd05 src/share/vm/runtime/signature.cpp
+--- a/src/share/vm/runtime/signature.cpp	Sat Jul 16 13:06:16 2011 +0100
++++ b/src/share/vm/runtime/signature.cpp	Sun Jul 17 13:13:57 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,30 @@
+       }
+       size = T_ARRAY_size;
+       break;
++    case '{':
++      if (TupleSignatures) {
++        switch(_signature->byte_at(_index + 1)) {
++          case 'V':
++            _index += 2; // Skip 'V' tag
++            break;
++
++          case 'L':
++            while (_signature->byte_at(_index++) != ';');
++            break;
++
++          default:
++            ShouldNotReachHere();
++            break;
++        }  
++        size = T_VOID_size;
++        break;
++      }
++    case '}':
++      if (TupleSignatures) {
++        _index++;
++        size = T_VOID_size;
++        break;
++      }
+     default:
+       ShouldNotReachHere();
+       break;
+@@ -304,6 +328,29 @@
+       break;
+     }
+     case ')': _end++; next(); _at_return_type = true; break;
++    case '{':
++      if (TupleSignatures) {
++        Symbol* sig = _signature;
++        switch(sig->byte_at(_end + 1)) {
++          case 'V':
++            _end += 2; // Skip 'V' tag
++            break;
++
++          case 'L':
++            while (sig->byte_at(_end++) != ';');
++            break;
++
++          default:
++            ShouldNotReachHere();
++            break;
++        }
++        next();
++        break;
++      }
++    case '}':
++      if (TupleSignatures) {
++        _end++; next(); break;
++      }
+     default : ShouldNotReachHere();
+   }
+ }
+@@ -445,7 +492,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 b0ff3165cd05 test/runtime/6804523/ClassTransformer.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/runtime/6804523/ClassTransformer.java	Sun Jul 17 13:13:57 2011 +0100
+@@ -0,0 +1,110 @@
++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");
++        transformer.transform("(JJ)J", "({Ljava/math/Rational;JJ})J");
++    }
++}
+diff -r b0ff3165cd05 test/runtime/6804523/SimpleBoyerMoore.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/runtime/6804523/SimpleBoyerMoore.java	Sun Jul 17 13:13:57 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:ja...@stacksmash.com">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 b0ff3165cd05 test/runtime/6804523/Test6804523.sh
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/runtime/6804523/Test6804523.sh	Sun Jul 17 13:13:57 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 -Xverify:none -XX:+TupleSignatures TestTupleSignature
+diff -r b0ff3165cd05 test/runtime/6804523/TestTupleSignature.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/runtime/6804523/TestTupleSignature.java	Sun Jul 17 13:13:57 2011 +0100
+@@ -0,0 +1,24 @@
++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"));
++		System.out.printf("{Ljava/math/Rational;JJ}: %s%n", 2701 + 1000000000L  == TupleSignature.staticRationalJJ(2701, 1000000000L));
++	}
++	
++}
+diff -r b0ff3165cd05 test/runtime/6804523/TupleSignature.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/runtime/6804523/TupleSignature.java	Sun Jul 17 13:13:57 2011 +0100
+@@ -0,0 +1,74 @@
++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;
++	}
++
++	public static long staticRationalJJ(long i, long j) {
++		return i + j;
++	}
++}
diff -r 527fde99eeaa series
--- a/series	Tue Jul 05 17:06:10 2011 -0700
+++ b/series	Sun Jul 17 13:16:17 2011 +0100
@@ -25,3 +25,4 @@
 anonk.patch                     #-/anonk #+502cc7f9d80d
 
 coro.patch                      #-/coro #+502cc7f9d80d
+tsigs.patch #+testable
diff -r 527fde99eeaa tsigs.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tsigs.patch	Sun Jul 17 13:16:17 2011 +0100
@@ -0,0 +1,331 @@
+diff -r a87a198b3630 make/docs/Makefile
+--- a/make/docs/Makefile	Sun Jun 19 15:58:35 2011 +0100
++++ b/make/docs/Makefile	Wed Jun 22 20:37:08 2011 +0100
+@@ -207,12 +207,7 @@
+                 -keywords				\
+ 		$(ADDITIONAL_JAVADOCFLAGS)
+ 
+-ifdef OPENJDK
+-  ADDITIONAL_JAVADOCFLAGS =				\
+-                -Xdocrootparent $(DOCS_BASE_URL)
+-else
+-  ADDITIONAL_JAVADOCFLAGS =
+-endif
++ADDITIONAL_JAVADOCFLAGS =
+ 
+ # Draft used for non-fcs documents
+ JDK_IS_FCS = false
+diff -r a87a198b3630 make/sun/security/jgss/wrapper/Makefile
+--- a/make/sun/security/jgss/wrapper/Makefile	Sun Jun 19 15:58:35 2011 +0100
++++ b/make/sun/security/jgss/wrapper/Makefile	Wed Jun 22 20:37:08 2011 +0100
+@@ -46,6 +46,10 @@
+ FILES_export = \
+     sun/security/jgss/wrapper/GSSLibStub.java
+ 
++ifeq ($(PLATFORM), linux)
++EXTRA_LIBS += -ldl
++endif
++
+ #
+ # Find native code
+ #
+diff -r a87a198b3630 make/sun/security/pkcs11/Makefile
+--- a/make/sun/security/pkcs11/Makefile	Sun Jun 19 15:58:35 2011 +0100
++++ b/make/sun/security/pkcs11/Makefile	Wed Jun 22 20:37:08 2011 +0100
+@@ -296,6 +296,10 @@
+ 	$(CP) $(PREBUILT_DIR)/pkcs11/sunpkcs11.jar $(JAR_DESTFILE)
+ endif
+ 
++ifeq ($(PLATFORM), linux)
++EXTRA_LIBS += -ldl
++endif
++
+ 
+ # =====================================================
+ # Support routines.
+diff -r a87a198b3630 src/share/native/common/check_code.c
+--- a/src/share/native/common/check_code.c	Sun Jun 19 15:58:35 2011 +0100
++++ b/src/share/native/common/check_code.c	Wed Jun 22 20:37:08 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
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to