diff src/main/gov/nasa/jpf/vm/Types.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/gov/nasa/jpf/vm/Types.java	Fri Jan 23 10:14:01 2015 -0800
@@ -0,0 +1,1156 @@
+/*
+ * Copyright (C) 2014, United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The Java Pathfinder core (jpf-core) platform is licensed under the
+ * Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0. 
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+package gov.nasa.jpf.vm;
+
+import gov.nasa.jpf.JPFException;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+
+/**
+ * various type mangling/demangling routines
+ *
+ * This reflects the general type id mess in Java. We support the following:
+ *
+ *  builtin type: byte - T_BOOLEAN and the like
+ *  type name: String - according to JLS 6.7 ("int", "x.Y[]")
+ *  type signature: String - like JNI ("I", "[Lx/Y;")
+ *  type classname: String - e.g. "int", "[I", "x.Y", "[Lx.Y;"
+ */
+public class Types {
+
+  // these have the same values as the BCEL Constants since we don't want to break compiled code
+  public static final byte T_NONE      = 0; // illegal type
+  
+  public static final byte T_BOOLEAN   = 4;
+  public static final byte T_BYTE      = 8;
+  public static final byte T_CHAR      = 5;
+  public static final byte T_SHORT     = 9;
+  public static final byte T_INT       = 10;
+  public static final byte T_LONG      = 11;
+  public static final byte T_FLOAT     = 6;
+  public static final byte T_DOUBLE    = 7;
+  public static final byte T_REFERENCE = 14;
+  public static final byte T_ARRAY     = 13;  // <2do> do we need this in addition to T_REFERENCE?
+  public static final byte T_VOID      = 12;
+
+  
+  public static byte[] getArgumentTypes (String signature) {
+    int i;
+    int j;
+    int nArgs;
+
+    for (i = 1, nArgs = 0; signature.charAt(i) != ')'; nArgs++) {
+      i += getTypeLength(signature, i);
+    }
+
+    byte[] args = new byte[nArgs];
+
+    for (i = 1, j = 0; j < nArgs; j++) {
+      int    end = i + getTypeLength(signature, i);
+      String arg = signature.substring(i, end);
+      i = end;
+
+      args[j] = getBuiltinTypeFromSignature(arg);
+    }
+
+    return args;
+  }
+
+  public static String[] getArgumentTypeNames (String signature) {
+    int len = signature.length();
+
+    if ((len > 1) && (signature.charAt(1) == ')')) {
+      return new String[0]; // 'no args' shortcut
+    }
+    
+    ArrayList<String> a = new ArrayList<String>();
+
+    for (int i = 1; signature.charAt(i) != ')';) {
+      int end = i + getTypeLength(signature,i);
+      String arg = signature.substring(i, end);
+      i = end;
+
+      a.add(getTypeName(arg));
+    }
+
+    String[] typeNames = new String[a.size()];
+    a.toArray(typeNames);
+    
+    return typeNames;
+  }
+  
+  public static String dequalify (String typeName){
+    int idx = typeName.lastIndexOf('.');
+    if (idx > 0) {
+      return typeName.substring(idx + 1);
+    } else {
+      return typeName;
+    }    
+  }
+  
+  public static String getDequalifiedMethodSignature (String mName){
+    int idx = mName.indexOf('(');
+    String sig = mName.substring(idx);
+    
+    return mName.substring(0, idx) + getDequalifiedArgumentSignature(sig);
+  }
+  
+  public static String getDequalifiedArgumentSignature (String sig){
+    String[] argTypes = getArgumentTypeNames(sig);
+    StringBuilder sb = new StringBuilder();
+    sb.append('(');
+    for (int i=0; i<argTypes.length; i++){
+      if (i>0){
+        sb.append(',');
+      }
+      sb.append(dequalify(argTypes[i]));
+    }
+    sb.append(')');
+    return sb.toString();
+  }
+  
+  public static String getDequalifiedTypeName (String sig){
+    String tn = getTypeName(sig);
+    return dequalify(tn);
+  }
+  
+  public static String getArgumentSignature (String[] typeNames, boolean qualified){
+    StringBuilder sb = new StringBuilder();
+    sb.append('(');
+    for (int i=0; i<typeNames.length; i++){
+      if (i>0){
+        sb.append(',');
+      }
+      
+      String tn = getTypeName(typeNames[i]);
+      if (!qualified){
+        int idx = tn.lastIndexOf('.');
+        if (idx >0){
+          tn = tn.substring(idx+1);
+        }
+      }
+      
+      sb.append( tn);
+    }
+    sb.append(')');
+    return sb.toString();
+  }
+  
+  /**
+   * get size in stack slots (ints), excluding this
+   */
+  public static int getArgumentsSize (String sig) {
+    int  n = 0;
+    for (int i = 1; sig.charAt(i) != ')'; i++) {
+      switch (sig.charAt(i)) {
+      case 'L':
+        do i++; while (sig.charAt(i) != ';');
+        n++;
+        break;
+      case '[':
+        do i++; while (sig.charAt(i) == '[');
+        if (sig.charAt(i) == 'L') {
+          do i++; while (sig.charAt(i) != ';');
+        }
+        n++;
+        break;
+      case 'J':
+      case 'D':
+        // the two-slot types
+        n += 2;
+        break;
+      default:
+        // just one slot entry
+        n++;
+      }
+    }
+    return n;
+  }
+
+  public static String getArrayElementType (String type) {
+    if (type.charAt(0) != '[') {
+      throw new JPFException("not an array type: " + type);
+    }
+
+    return type.substring(1);
+  }
+
+  public static String getComponentTerminal (String type) {
+    if (type.charAt(0) != '[') {
+      throw new JPFException("not an array type: " + type);
+    }
+
+    if(isReferenceSignature(type)) {
+      return type.substring(type.indexOf('L') + 1 , type.indexOf(';'));
+    } else {
+      return type.substring(type.lastIndexOf('[') + 1);
+    }
+  }
+
+  public static byte getBuiltinTypeFromSignature (String signature) {
+    switch (signature.charAt(0)) {
+    case 'B':
+      return T_BYTE;
+
+    case 'C':
+      return T_CHAR;
+
+    case 'D':
+      return T_DOUBLE;
+
+    case 'F':
+      return T_FLOAT;
+
+    case 'I':
+      return T_INT;
+
+    case 'J':
+      return T_LONG;
+
+    case 'L':
+      return T_REFERENCE;
+
+    case 'S':
+      return T_SHORT;
+
+    case 'V':
+      return T_VOID;
+
+    case 'Z':
+      return T_BOOLEAN;
+
+    case '[':
+      return T_ARRAY;
+    }
+
+    throw new JPFException("invalid type string: " + signature);
+  }
+
+  /**
+   * get the argument type part of the signature out of a
+   * JNI mangled method name.
+   * Note this is not the complete signature, since we don't have a
+   * return type (which is superfluous since it's not overloading,
+   * but unfortunately part of the signature in the class file)
+   */
+  public static String getJNISignature (String mangledName) {
+    int    i = mangledName.indexOf("__");
+    String sig = null;
+
+    if (i > 0) {
+      int k = 0;      
+      int r = mangledName.indexOf("__", i+2); // maybe there is a return type part
+      boolean gotReturnType = false;
+      int len = mangledName.length();
+      char[] buf = new char[len + 2];
+
+      buf[k++] = '(';
+
+      for (i += 2; i < len; i++) {
+
+        if (i == r) { // here comes the return type part (that's not JNI, only MJI
+          if ((i + 2) < len) {
+            i++;
+            buf[k++] = ')';
+            gotReturnType = true;
+            continue;
+          } else {
+            break;
+          }
+        }
+        
+        char c = mangledName.charAt(i);
+        if (c == '_') {
+          i++;
+
+          if (i < len) {
+            c = mangledName.charAt(i);
+
+            switch (c) {
+            case '1':
+              buf[k++] = '_';
+
+              break;
+
+            case '2':
+              buf[k++] = ';';
+
+              break;
+
+            case '3':
+              buf[k++] = '[';
+
+              break;
+
+            default:
+              buf[k++] = '/';
+              buf[k++] = c;
+            }
+          } else {
+            buf[k++] = '/';
+          }
+        } else {
+          buf[k++] = c;
+        }
+      }
+
+      if (!gotReturnType) {
+        // if there was no return type spec, assume 'void'
+        buf[k++] = ')';
+        buf[k++] = 'V';
+      }
+        
+      sig = new String(buf, 0, k);
+    }
+
+    // Hmm, maybe we should return "()V" instead of null, but that seems a bit too assuming
+    return sig;
+  }
+
+  public static String getJNIMangledMethodName (Method m) {
+    String      name = m.getName();
+    Class<?>[]    pt = m.getParameterTypes();
+    StringBuilder  s = new StringBuilder(name.length() + (pt.length * 16));
+
+    s.append(name);
+    s.append("__");
+
+    // <2do> not very efficient, but we don't care for now
+    for (int i = 0; i < pt.length; i++) {
+      s.append(getJNITypeCode(pt[i].getName()));
+    }
+
+    // the return type part, which is not in JNI, but is required for
+    // handling covariant return types
+    Class<?> rt = m.getReturnType();
+    s.append("__");
+    s.append(getJNITypeCode(rt.getName()));
+    
+    return s.toString();
+  }
+
+  public static String getJNIMangledMethodName (String cls, String name,
+                                                String signature) {
+    StringBuilder s = new StringBuilder(signature.length() + 10);
+    int           i;
+    char          c;
+    int           slen = signature.length();
+    
+    if (cls != null) {
+      s.append(cls.replace('.', '_'));
+    }
+
+    s.append(name);
+    s.append("__");
+
+    // as defined in the JNI specs
+    for (i = 1; i<slen; i++) {
+      c = signature.charAt(i);
+      switch (c) {
+      case '/':
+        s.append('_');
+        break;
+
+      case '_':
+        s.append("_1");
+        break;
+
+      case ';':
+        s.append("_2");
+        break;
+
+      case '[':
+        s.append("_3");
+        break;
+
+      case ')':
+        // the return type part - note this is not JNI, but saves us a lot of trouble with
+        // the covariant return types of Java 1.5        
+        s.append("__");
+        break;
+        
+      default:
+        s.append(c);
+      }
+    }
+
+    return s.toString();
+  }
+
+  /**
+   * return the name part of a JNI mangled method name (which is of
+   * course not completely safe - you should only use it if you know
+   * this is a JNI name)
+   */
+  public static String getJNIMethodName (String mangledName) {
+    // note that's the first '__' group, which marks the beginning of the arg types
+    int i = mangledName.indexOf("__");
+
+    if (i > 0) {
+      return mangledName.substring(0, i);
+    } else {
+      return mangledName;
+    }
+  }
+
+  /**
+   * type is supposed to be Class.getName conforming, i.e.
+   * 
+   * int    -> int
+   * int[]  -> [I
+   * String -> java.lang.String
+   * String[] -> [Ljava.lang.String;
+   * String[][] -> [[Ljava.lang.String;
+   * 
+   * <2do> this is really not very efficient
+   */
+  public static String getJNITypeCode (String type) {
+    StringBuilder sb = new StringBuilder(32);
+    int l = type.length() - 1;
+    int i;
+
+    // Class.getName arrays "[...type"
+    for ( i=0; type.charAt(i) == '['; i++){
+      sb.append("_3");
+    }
+    
+    // conventional arrays "type[]..."
+    for (; type.charAt(l) == ']'; l -= 2) {
+      sb.append("_3");
+    }
+
+    type = type.substring(i, l + 1);
+
+    if (type.equals("int") || type.equals("I")) {
+      sb.append('I');
+    } else if (type.equals("long") || type.equals("J")) {
+      sb.append('J');
+    } else if (type.equals("boolean") || type.equals("Z")) {
+      sb.append('Z');
+    } else if (type.equals("char") || type.equals("C")) {
+      sb.append('C');
+    } else if (type.equals("byte")  || type.equals("B")) {
+      sb.append('B');
+    } else if (type.equals("short") || type.equals("S")) {
+      sb.append('S');
+    } else if (type.equals("double") || type.equals("D")) {
+      sb.append('D');
+    } else if (type.equals("float") || type.equals("F")) {
+      sb.append('F');
+    } else if (type.equals("void") || type.equals("V")) {  // for return types
+      sb.append('V');
+    } else { // reference type
+      if (type.charAt(0) != 'L'){
+        sb.append('L');
+      }
+
+      l = type.length();
+      for (i=0; i < l; i++) {
+        char c = type.charAt(i);
+
+        switch (c) {
+        case '.':
+          sb.append('_');
+          break;
+
+        case '_':
+          sb.append("_1");
+          break;
+          
+        case ';':
+          break;
+          
+        default:
+          sb.append(c);
+        }
+      }
+
+      sb.append("_2");
+      
+    }
+
+    return sb.toString();
+  }
+
+  // this includes the return type part
+  public static int getNumberOfStackSlots (String signature, boolean isStatic) {
+    int nArgSlots = 0;
+    int n = isStatic ? 0 : 1;
+    int sigLen = signature.length();
+
+    for (int i = 1; i < sigLen; i++) {
+      switch (signature.charAt(i)) {
+      case ')' : // end of arg part, but there still might be a return type
+        nArgSlots = n;
+        n = 0;
+        break;
+      case 'L':   // reference = 1 slot
+        i = signature.indexOf(';', i);
+        n++;
+        break;
+      case '[':
+        do i++; while (signature.charAt(i) == '[');
+        if (signature.charAt(i) == 'L') {
+          i = signature.indexOf(';', i);
+        }
+        n++;
+        break;
+      case 'J':
+      case 'D':
+        n+=2;
+        break;
+      default:
+        n++;
+      }
+    }
+    
+    return Math.max(n, nArgSlots);
+  }
+  
+  public static int getNumberOfArguments (String signature) {
+    int  i,n;
+    int sigLen = signature.length();
+
+    for (i = 1, n = 0; i<sigLen; n++) {
+      switch (signature.charAt(i)) {
+      case ')' :
+        return n;
+      case 'L':
+        do i++; while (signature.charAt(i) != ';');
+        break;
+
+      case '[':
+        do i++; while (signature.charAt(i) == '[');
+        if (signature.charAt(i) == 'L') {
+          do i++; while (signature.charAt(i) != ';');
+        }
+        break;
+
+      default:
+        // just a single type char
+      }
+
+      i++;
+    }
+
+    assert (false) : "malformed signature: " + signature;
+    return n; // that would be a malformed signature
+  }
+
+  public static boolean isReferenceSignature(String signature){
+    return signature.charAt(signature.length()-1) == ';';
+  }
+
+  public static boolean isReference (String type) {
+    int t = getBuiltinTypeFromSignature(type);
+
+    return (t == T_ARRAY) || (t == T_REFERENCE);
+  }
+
+  public static boolean isArray (String type) {
+    int t = getBuiltinTypeFromSignature(type);
+
+    return (t == T_ARRAY);
+  }
+
+  public static byte getReturnBuiltinType (String signature) {
+    int i = signature.indexOf(')');
+
+    return getBuiltinTypeFromSignature(signature.substring(i + 1));
+  }
+
+  public static String getReturnTypeSignature(String signature){
+    int i = signature.indexOf(')');
+    return signature.substring(i + 1);
+  }
+
+  public static String getReturnTypeName (String signature){
+    int i = signature.indexOf(')');
+    return getTypeName(signature.substring(i+1));
+  }
+  
+  public static String getTypeSignature (String type, boolean asDotNotation) {
+    String  t = null;
+    int arrayDim = 0;
+    
+    type = asDotNotation ? type.replace('/', '.') : type.replace('.', '/');
+    
+    if ((type.charAt(0) == '[') || (type.endsWith(";"))) {  // [[[L...;
+      t = type;
+      
+    } else {
+      
+      while (type.endsWith("[]")) { // type[][][]
+        type = type.substring(0, type.length() - 2);
+        arrayDim++;
+      }
+      
+      if (type.equals("byte")) {
+        t = "B";
+      } else if (type.equals("char")) {
+        t = "C";
+      } else if (type.equals("short")) {
+        t = "S";
+      } else if (type.equals("int")) {
+        t = "I";
+      } else if (type.equals("float")) {
+        t = "F";
+      } else if (type.equals("long")) {
+        t = "J";
+      } else if (type.equals("double")) {
+        t = "D";
+      } else if (type.equals("boolean")) {
+        t = "Z";
+      } else if (type.equals("void")) {
+        t = "V";
+      } else if (type.endsWith(";")) {
+        t = type;
+        
+      } else {
+        t = "L" + type + ';';
+      }
+      
+      while (arrayDim-- > 0) {
+        t = "[" + t;
+      }
+    }
+
+    return t;
+  }
+
+  public static byte getBuiltinType(String typeName){
+      if (typeName.equals("byte")) {
+        return T_BYTE;
+      } else if (typeName.equals("char")) {
+        return T_CHAR;
+      } else if (typeName.equals("short")) {
+        return T_SHORT;
+      } else if (typeName.equals("int")) {
+        return T_INT;
+      } else if (typeName.equals("float")) {
+        return T_FLOAT;
+      } else if (typeName.equals("long")) {
+        return T_LONG;
+      } else if (typeName.equals("double")) {
+        return T_DOUBLE;
+      } else if (typeName.equals("boolean")) {
+        return T_BOOLEAN;
+      } else if (typeName.equals("void")) {
+        return T_VOID;
+      } else {
+        if (typeName.charAt(typeName.length()-1) == ']'){
+          return T_ARRAY;
+        } else {
+          return T_REFERENCE;
+        }
+      }
+  }
+
+  public static String getBoxedType (byte type) {
+	  switch (type) {
+	  case Types.T_BOOLEAN:
+		  return "Boolean";
+	  case Types.T_BYTE:
+		  return "Byte";
+	  case Types.T_CHAR:
+		  return "Character";
+	  case Types.T_SHORT:
+		  return "Short";
+	  case Types.T_INT:
+		  return "Integer";
+	  case Types.T_LONG:
+		  return "Long";
+	  case Types.T_FLOAT:
+		  return "Float";
+	  case Types.T_DOUBLE:
+		  return "Double";
+	  default:
+		  return null;
+	  }
+  }
+  
+  public static byte getUnboxedType (String typeName){
+    if (typeName.startsWith("java.lang.")){
+      typeName = typeName.substring(10);
+      if (typeName.equals("Boolean")){
+        return T_BOOLEAN;
+      } else if (typeName.equals("Byte")){
+        return T_BYTE;
+      } else if (typeName.equals("Character")){
+        return T_CHAR;
+      } else if (typeName.equals("Short")){
+        return T_SHORT;
+      } else if (typeName.equals("Integer")){
+        return T_INT;
+      } else if (typeName.equals("Long")){
+        return T_LONG;
+      } else if (typeName.equals("Float")){
+        return T_FLOAT;
+      } else if (typeName.equals("Double")){
+        return T_DOUBLE;
+      }
+    }
+    
+    // everything else can't be a box type
+    if (typeName.charAt(0) == '[' || typeName.charAt(typeName.length()-1) == ']'){
+      return T_ARRAY;
+    } else {
+      return T_REFERENCE;
+    }
+  }
+  
+  public static String getClassNameFromSignature (String signature){
+    if (signature.charAt(signature.length()-1) == ';'){ // reference
+      return signature.replace('/', '.');
+
+    } else { // builtin
+      switch (signature.charAt(0)){
+        case 'Z': return "boolean";
+        case 'B': return "byte";
+        case 'C': return "char";
+        case 'S': return "short";
+        case 'I': return "int";
+        case 'J': return "long";
+        case 'F': return "float";
+        case 'D': return "double";
+        default:
+          throw new JPFException("illegal type signature: " + signature);
+      }
+    }
+  }
+
+  /**
+   * get the canonical representation of a type name, which happens to be
+   *  (1) the name of the builtin type (e.g. "int")
+   *  (2) the normal dot name for ordinary classes (e.g. "java.lang.String")
+   *  (3) the coded dot name for arrays (e.g. "[B", "[[C", or "[Ljava.lang.String;")
+   *  
+   * not sure if we need to support internal class names (which use '/'
+   * instead of '.' as separators
+   *  
+   * no idea what's the logic behind this, but let's implement it
+   */
+  public static String getClassNameFromTypeName (String typeName) {
+    typeName = typeName.replace('/','.');
+    int n = typeName.length()-1;
+    
+    if (typeName.charAt(0) == '['){ // the "[<type>" notation
+      if (typeName.charAt(1) == 'L'){
+        if (typeName.charAt(n) != ';'){
+          typeName = typeName + ';';
+        }
+      }
+      
+      return typeName;
+    }
+    
+    int i=typeName.indexOf('[');
+    if (i>0){ // the sort of "<type>[]"
+      StringBuilder sb = new StringBuilder();
+      sb.append('[');
+      for (int j=i; (j=typeName.indexOf('[',j+1)) >0;){
+        sb.append('[');
+      }
+      
+      typeName = typeName.substring(0,i);
+      if (isBasicType(typeName)){
+        sb.append( getTypeSignature(typeName, true));
+      } else {
+        sb.append('L');
+        sb.append(typeName);
+        sb.append(';');
+      }
+      
+      return sb.toString();
+    }
+    
+    if (typeName.charAt(n) == ';') {
+      return typeName.substring(1,n);
+    }
+    
+    return typeName;
+  }
+
+  
+  public static boolean isTypeCode (String t) {
+    char c = t.charAt(0);
+
+    if (c == '[') {
+      return true;
+    }
+
+    if ((t.length() == 1) &&
+            ((c == 'B') || (c == 'I') || (c == 'S') || (c == 'C') ||
+              (c == 'F') || (c == 'J') || (c == 'D') || (c == 'Z'))) {
+      return true;
+    }
+
+    if (t.endsWith(";")) {
+      return true;
+    }
+
+    return false;
+  }
+
+  public static boolean isBasicType (String typeName){
+    return ("boolean".equals(typeName) ||
+        "byte".equals(typeName) ||
+        "char".equals(typeName) ||
+        "int".equals(typeName) ||
+        "long".equals(typeName) ||
+        "double".equals(typeName) ||
+        "short".equals(typeName) ||
+        "float".equals(typeName));
+  }
+
+  public static byte getTypeCode (String signature){
+    char c = signature.charAt(0);
+
+    switch (c) {
+      case 'B':
+        return T_BYTE;
+
+      case 'C':
+        return T_CHAR;
+
+      case 'D':
+        return T_DOUBLE;
+
+      case 'F':
+        return T_FLOAT;
+
+      case 'I':
+        return T_INT;
+
+      case 'J':
+        return T_LONG;
+
+      case 'L':
+        return T_REFERENCE;
+
+      case 'S':
+        return T_SHORT;
+
+      case 'V':
+        return T_VOID;
+
+      case 'Z':
+        return T_BOOLEAN;
+
+      case '[':
+        return T_ARRAY;
+
+      default:
+        throw new JPFException("unknow typecode: " + signature);
+    }
+  }
+  
+  /**
+   * return the qualified signature name according to JLS 6.7 (e.g. "int", "x.Y[]")
+   */
+  public static String getTypeName (String signature) {
+    int  len = signature.length();
+    char c = signature.charAt(0);
+
+    if (len == 1) {
+      switch (c) {
+      case 'B':
+        return "byte";
+
+      case 'C':
+        return "char";
+
+      case 'D':
+        return "double";
+
+      case 'F':
+        return "float";
+
+      case 'I':
+        return "int";
+
+      case 'J':
+        return "long";
+
+      case 'S':
+        return "short";
+
+      case 'V':
+        return "void";
+
+      case 'Z':
+        return "boolean";
+      }
+    }
+
+    if (c == '[') {
+      return getTypeName(signature.substring(1)) + "[]";
+    }
+
+    int len1 = len-1;
+    if (signature.charAt(len1) == ';') {
+      return signature.substring(1, len1).replace('/', '.');
+    }
+
+    throw new JPFException("invalid type string: " + signature);
+  }
+
+  /** thoses are according to the arrayType codes of the newarray JVMS definition */
+  public static String getElementDescriptorOfType (int arrayType){
+    switch (arrayType){
+      case 4: return "Z";
+      case 5: return "C";
+      case 6: return "F";
+      case 7: return "D";
+      case 8: return "B";
+      case 9: return "S";
+      case 10: return "I";
+      case 11: return "J";
+    }
+    return null;
+  }
+
+  /**
+   * what would be the info size in bytes, not words
+   * (we ignore 64bit machines for now)
+   */
+  public static int getTypeSizeInBytes (String signature) {
+    switch (signature.charAt(0)) {
+      case 'V':
+        return 0;
+        
+      case 'Z': // that's a stretch, but we assume boolean uses the smallest addressable size
+      case 'B':
+        return 1;
+        
+      case 'S':
+      case 'C':
+        return 2;
+        
+      case 'L':
+      case '[':
+      case 'F':
+      case 'I':
+        return 4;
+        
+      case 'D':
+      case 'J':
+        return 8;
+    }
+
+    throw new JPFException("invalid type string: " + signature);
+  }
+  
+  public static int getTypeSize (String signature) {
+    switch (signature.charAt(0)) {
+    case 'V':
+      return 0;
+
+    case 'B':
+    case 'C':
+    case 'F':
+    case 'I':
+    case 'L':
+    case 'S':
+    case 'Z':
+    case '[':
+      return 1;
+
+    case 'D':
+    case 'J':
+      return 2;
+    }
+
+    throw new JPFException("invalid type string: " + signature);
+  }
+
+  public static int getTypeSize (byte typeCategory){
+    if (typeCategory == T_LONG || typeCategory == T_DOUBLE){
+      return 2;
+    } else {
+      return 1;
+    }
+  }
+  
+  public static String asTypeName (String type) {
+    if (type.startsWith("[") || type.endsWith(";")) {
+      return getTypeName(type);
+    }
+
+    return type;
+  }
+
+  public static int booleanToInt (boolean b) {
+    return b ? 1 : 0;
+  }
+
+  public static long doubleToLong (double d) {
+    return Double.doubleToLongBits(d);
+  }
+
+  public static int floatToInt (float f) {
+    return Float.floatToIntBits(f);
+  }
+
+  public static int hiDouble (double d) {
+    return hiLong(Double.doubleToLongBits(d));
+  }
+
+  public static int hiLong (long l) {
+    return (int) (l >> 32);
+  }
+
+  public static boolean instanceOf (String type, String ofType) {
+    int bType = getBuiltinTypeFromSignature(type);
+
+    if ((bType == T_ARRAY) && ofType.equals("Ljava.lang.Object;")) {
+      return true;
+    }
+
+    int bOfType = getBuiltinTypeFromSignature(ofType);
+
+    if (bType != bOfType) {
+      return false;
+    }
+
+    switch (bType) {
+    case T_ARRAY:
+      return instanceOf(type.substring(1), ofType.substring(1));
+
+    case T_REFERENCE:
+      ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(getTypeName(type));
+      return ci.isInstanceOf(getTypeName(ofType));
+
+    default:
+      return true;
+    }
+  }
+
+  public static boolean intToBoolean (int i) {
+    return i != 0;
+  }
+
+  public static float intToFloat (int i) {
+    return Float.intBitsToFloat(i);
+  }
+
+  public static double intsToDouble (int l, int h) {
+    long bits = ((long) h << 32) | (/*(long)*/ l & 0xFFFFFFFFL);
+    return Double.longBitsToDouble(bits);
+  }
+
+  public static long intsToLong (int l, int h) {
+    return ((long) h << 32) | (/*(long)*/ l & 0xFFFFFFFFL);
+  }
+
+  public static int loDouble (double d) {
+    return loLong(Double.doubleToLongBits(d));
+  }
+
+  public static int loLong (long l) {
+    return (int) (l & 0xFFFFFFFFL);
+  }
+
+  public static double longToDouble (long l) {
+    return Double.longBitsToDouble(l);
+  }
+
+  private static int getTypeLength (String signature, int idx) {
+    switch (signature.charAt(idx)) {
+    case 'B':
+    case 'C':
+    case 'D':
+    case 'F':
+    case 'I':
+    case 'J':
+    case 'S':
+    case 'V':
+    case 'Z':
+      return 1;
+
+    case '[':
+      return 1 + getTypeLength(signature, idx + 1);
+
+    case 'L':
+
+      int semicolon = signature.indexOf(';', idx);
+
+      if (semicolon == -1) {
+        throw new JPFException("invalid type signature: " +
+                                         signature);
+      }
+
+      return semicolon - idx + 1;
+    }
+
+    throw new JPFException("invalid type signature");
+  }
+
+  /**
+   * return the JPF internal representation of a method signature that is given
+   * in dot-notation (like javap),
+   *
+   *  e.g.  "int foo(int[],java.lang.String)" -> "foo([ILjava/lang/String;)I"
+   *
+   */
+  public static String getSignatureName (String methodDecl) {
+
+    StringBuffer sb = new StringBuffer(128);
+    String retType = null;
+
+    int i = methodDecl.indexOf('(');
+    if (i>0){
+
+      //--- name and return type
+      String[] a = methodDecl.substring(0, i).split(" ");
+      if (a.length > 0){
+        sb.append(a[a.length-1]);
+
+        if (a.length > 1){
+          retType = getTypeSignature(a[a.length-2], false);
+        }
+      }
+
+      //--- argument types
+      int j = methodDecl.lastIndexOf(')');
+      if (j > 0){
+        sb.append('(');
+        for (String type : methodDecl.substring(i+1,j).split(",")){
+          if (!type.isEmpty()){
+            type = type.trim();
+            if (!type.isEmpty()){
+              sb.append( getTypeSignature(type,false));
+            }
+          }
+        }
+        sb.append(')');
+
+        if (retType != null){
+          sb.append(retType);
+        }
+
+        return sb.toString();
+      }
+    }
+
+    throw new JPFException("invalid method declaration: " + methodDecl);
+  }
+  
+}