Example #1
0
 public void dumpReplayData(PrintStream out) {
   NMethod nm = getNativeMethod();
   int code_size = 0;
   if (nm != null) {
     code_size = (int) nm.codeEnd().minus(nm.getVerifiedEntryPoint());
   }
   Klass holder = getMethodHolder();
   out.println(
       "ciMethod "
           + holder.getName().asString()
           + " "
           + OopUtilities.escapeString(getName().asString())
           + " "
           + getSignature().asString()
           + " "
           + getInvocationCount()
           + " "
           + getBackedgeCount()
           + " "
           + interpreterInvocationCount()
           + " "
           + interpreterThrowoutCount()
           + " "
           + code_size);
 }
Example #2
0
  /**
   * Verifies that the current state of the local variables array matches the state specified by a
   * stack map entry.
   *
   * @param target the target encapsulating a stack map entry specifying what the current state of
   *     the local variables array should be
   * @param replaceWithTarget if true, then the current state of the local variable array is updated
   *     to reflect the state recorded in the stack map entry
   */
  public void mergeLocals(Target target, boolean replaceWithTarget) {
    Klass[] recordedTypes = target.getLocals();
    if (recordedTypes.length > localTypes.length) {
      throw codeParser.verifyError("size of recorded and derived local variable array differs");
    }

    /*
     * Check the locals
     */
    for (int i = 0; i < recordedTypes.length; i++) {
      Klass recordedType = recordedTypes[i];
      Klass derivedType = localTypes[i];
      if (!recordedType.isAssignableFrom(derivedType)) {
        /*
         * For some reason, the preverifier occasionally generates
         * stack map entries for local variables even though the
         * local variable is dead. What's more, in these cases,
         * it determines that the type resulting from merging an
         * object type and an interface type is the interface
         * type. This makes no sense to me, but the case must be
         * allowed.
         */
        if (!recordedType.isInterface() || derivedType.isPrimitive()) {
          throw codeParser.verifyError("invalid type in local variable");
        }
      }
      if (replaceWithTarget) {
        localTypes[i] = recordedType;
      }
    }
  }
Example #3
0
 /**
  * Gets the super class of this class.
  *
  * @return the super class of this class
  */
 public final ProxyType getSuperclass() throws IOException, SDWPException {
   Klass superClass = klass.getSuperclass();
   // the "-bytecode-" class actually inherits from INT, but don't tell jdwp that!
   if (superClass != null && !superClass.isPrimitive()) {
     return ptm.lookup(superClass, true);
   }
   return null;
 }
Example #4
0
 @SuppressWarnings("unchecked")
 private void addFields(List list, boolean isStatic) {
   int count = klass.getFieldCount(isStatic);
   for (int i = 0; i != count; ++i) {
     Field field = klass.getField(i, isStatic);
     FieldID fid = new FieldID(JDWP.getTag(field.getType()), field.getOffset(), isStatic, getID());
     ProxyField proxyField = new ProxyField(fid, field);
     list.add(proxyField);
   }
 }
Example #5
0
 /**
  * Gets the class file corresponding to a given instance class. The <code>klass</code> must not
  * yet be converted and it must not be a {@link Klass#isSynthetic() synthetic} class.
  *
  * @param klass the instance class for which a class file is requested
  * @return the class file for <code>klass</code>
  */
 ClassFile getClassFile(Klass klass) {
   Assert.that(!klass.isSynthetic(), "synthethic class has no classfile");
   String name = klass.getName();
   ClassFile classFile = (ClassFile) classFiles.get(name);
   if (classFile == null) {
     classFile = new ClassFile(klass);
     classFiles.put(name, classFile);
   }
   return classFile;
 }
Example #6
0
 /**
  * Emulates the storing of a value to a local variable.
  *
  * @param index the index of the local variable being stored to
  * @param type the type of the value
  * @param local the variable to which the value is stored
  */
 public void store(int index, Klass type, Local local) {
   Klass localType = local.getType();
   Assert.that(localType.isAssignableFrom(type) || localType == getLocalTypeFor(type));
   verifyLocalVariableIndex(localType, index);
   localTypes[index] = type;
   if (localType.isDoubleWord()) {
     localTypes[index + 1] = Klass.getSecondWordType(localType);
   } else {
     verifyUseOfSquawkPrimitive(localType, type);
   }
 }
Example #7
0
 @SuppressWarnings("unchecked")
 private void addMethods(List list, boolean isStatic) {
   int count = klass.getMethodCount(isStatic);
   for (int i = 0; i != count; ++i) {
     Method method = klass.getMethod(i, isStatic);
     if (!method.isHosted()) {
       MethodID mid = new MethodID(method.getOffset(), isStatic);
       ProxyMethod proxyMethod = new ProxyMethod(mid, method);
       list.add(proxyMethod);
     }
   }
 }
Example #8
0
  /**
   * Gets the fully qualified name of this type. The returned name is formatted as it might appear
   * in a Java programming language declaration for objects of this type.
   *
   * <p>For primitive classes the returned name is the name of the corresponding primitive type; for
   * example, "int" is returned as the name of the class represented by {@link
   * java.lang.Integer#TYPE Integer.TYPE}.
   *
   * @return a string containing the type name.
   */
  public String getName() {
    String name = klass.getName();
    if (!klass.isArray()) {
      return name;
    }

    int dimensions = 0;
    while (name.charAt(dimensions) == '[') {
      ++dimensions;
    }

    name = name.substring(dimensions);
    char first = name.charAt(0);
    if (first == 'L') {
      name = name.substring(1, name.length() - 2).replace('/', '.');
    } else {
      switch (first) {
        case 'I':
          name = "int";
          break;
        case 'J':
          name = "long";
          break;
        case 'F':
          name = "float";
          break;
        case 'D':
          name = "double";
          break;
        case 'Z':
          name = "boolean";
          break;
        case 'C':
          name = "char";
          break;
        case 'S':
          name = "short";
          break;
        case 'B':
          name = "byte";
          break;
        case 'V':
          name = "void";
          break;
      }
    }
    while (dimensions-- != 0) {
      name += "[]";
    }
    return name;
  }
Example #9
0
 /**
  * Determines if the operand stack or local variable array currently contains an entry whose type
  * is equal to or a subtype of a given type.
  *
  * @param type the type to search for
  * @return true if an entry was found
  */
 public boolean containsType(Klass type) {
   for (int i = 0; i < localTypes.length; i++) {
     if (type.isAssignableFrom(localTypes[i])) {
       return true;
     }
   }
   for (int i = 0; i < sp; i++) {
     StackProducer producer = stack[i];
     if (producer != null && type.isAssignableFrom(producer.getType())) {
       return true;
     }
   }
   return false;
 }
Example #10
0
 /** {@inheritDoc} */
 public void load(Klass klass) {
   Assert.that(VM.isHosted() || VM.getCurrentIsolate().getLeafSuite() == suite);
   int state = klass.getState();
   if (state < Klass.STATE_LOADED) {
     if (klass.isArray()) {
       load(klass.getComponentType());
     } else {
       lastClassNameStack.push(klass.getName());
       ClassFile classFile = getClassFile(klass);
       load(classFile);
       lastClassNameStack.pop();
     }
   }
 }
Example #11
0
  /**
   * Get a <code>Local</code> instance to represent a value of a given type that will be
   * stored/loaded to/from a given local variable.
   *
   * @param type the type of the value
   * @param index the index of the local variable
   * @param isParameter true if the local is a parameter
   * @return the variable at index <code>index</code> in which values of type <code>type</code> are
   *     stored
   */
  private Local allocateLocalPrim(Klass type, int index, boolean isParameter) {
    Assert.that(localTypes.length < 0xFFFF);
    Assert.that(
        index >= 0 && index < localTypes.length,
        "index=" + index + " localTypes.length=" + localTypes.length);

    Klass localType = getLocalTypeFor(type);

    int key = localType.getSuiteID();

    /* We need a hard partition between uses of a slot as a reference vs. an Address, Offset, or UWord.
     * The partitioning of java primitives and objects is accomplished not only by the type passed in here, but
     * by the bytecode verifier. We can't be sure that some bytecodes are refering to the same local variable
     * as both a reference and as a Squawk primitive. Without that kind of support we are conservative here
     * and force a clash whenever javac uses the same local index for a reference and a Squawk primitive.
     */
    if (localType.isSquawkPrimitive()) {
      key = Klass.REFERENCE.getSuiteID();
    }
    key = key << 16 | index;
    if (localValues == null) {
      localValues = new IntHashtable();
    }
    Local local = (Local) localValues.get(key);
    if (local == null) {
      local = new Local(localType, index, isParameter);
      localValues.put(key, local);
    }

    /*
     * Ensure that the original class file does not use the same local variable
     * for both a Squawk primitive value and any other reference value. This prevents the
     * translator from having to do a complete liveness analysis to de-multiplex
     * such a local variable slot. Such de-multiplexing is required as Squawk primitives
     * are 'magically' translated into integers (or longs on a 64 bit system).
     */
    if (localType.isSquawkPrimitive() || local.getType().isSquawkPrimitive()) {
      if (localType != local.getType()) {
        throw codeParser.verifyError(
            getBadAddressLocalVariableMessage(index, localType, local.getType()));
      }
    }

    // System.out.println("allocated: "+local+" index "+index);
    /// *if[SCOPEDLOCALVARIABLES]*/
    codeParser.localVariableAllocated(codeParser.getCurrentIP(), local);
    /// *end[SCOPEDLOCALVARIABLES]*/
    return local;
  }
Example #12
0
  /**
   * Pops a value off the operand stack.
   *
   * @param type the type that the value popped off the operand stack must be assignable to
   * @return the instruction that produced the popped value
   */
  public StackProducer pop(Klass type) {
    StackProducer producer;
    if (type.isDoubleWord()) {
      if (sp < 2) {
        throw codeParser.verifyError("operand stack underflow");
      }
      if (!isTopDoubleWord()) {
        throw codeParser.verifyError("incompatible type on operand stack " + tosKlassName());
      }
      sp -= 2;
      producer = stack[sp];
    } else {
      if (sp < 1) {
        throw codeParser.verifyError("operand stack underflow");
      }
      if (isTopDoubleWord()) {
        throw codeParser.verifyError("incompatible type on operand stack " + tosKlassName());
      }
      producer = stack[--sp];

      /*
       * The primitive one-word, non-float types are all assignment compatible with each other
       */
      if (type.isPrimitive() && type != Klass.FLOAT) {

        type = Klass.INT;
      }
    }

    Assert.that(producer != null);

    /*
     * Interfaces are treated as java.lang.Object in the verifier.
     */
    if (type.isInterface()) {
      type = Klass.OBJECT;
    }

    /*
     * Verify that the instruction is producing the correct type.
     */
    if (!type.isAssignableFrom(producer.getType())) {
      throw codeParser.verifyError(
          "incompatible type: '" + type + "' is not assignable from '" + producer.getType() + "'");
    }

    return producer;
  }
Example #13
0
 /**
  * Gets the type of a local variable that is used to store a value of a given class. This method
  * partitions all classes into one of the following categories:
  *
  * <p>
  *
  * <blockquote>
  *
  * <pre>
  *
  *     Local Variable Type  |  Types
  *     ---------------------+-------
  *     INT                  | boolean, byte, short, int
  *     FLOAT                | float
  *     LONG                 | long
  *     DOUBLE               | double
  *     ADDRESS              | Address
  *     UWORD                | UWord
  *     OFFSET               | Offset
  *     REFERENCE            | types in java.lang.Object hierarchy
  *
  * </pre>
  *
  * </blockquote>
  *
  * <p>
  *
  * @param type the type of a value that will be stored in a local variable
  * @return the local variable type for storing values of type <code>type</code>
  */
 public static Klass getLocalTypeFor(Klass type) {
   switch (type.getSystemID()) {
     case CID.BOOLEAN:
     case CID.BYTE:
     case CID.SHORT:
     case CID.CHAR:
     case CID.INT:
       {
         return Klass.INT;
       }
     case CID.FLOAT:
     case CID.LONG:
     case CID.DOUBLE:
       {
         return type;
       }
     case CID.UWORD:
     case CID.OFFSET:
     case CID.ADDRESS:
       {
         return type;
       }
     default:
       {
         Assert.that(Klass.REFERENCE.isAssignableFrom(type));
         return Klass.REFERENCE;
       }
   }
 }
 boolean computeSubtypeOf(Klass k) {
   if (k.isInterface()) {
     return implementsInterface(k);
   } else {
     return super.computeSubtypeOf(k);
   }
 }
Example #15
0
 /**
  * Generate squawk code for methods of <code>klass</code> when doing whole-suite translation
  * (inlining, etc.)
  *
  * @param klass the klass to generate code for
  */
 void convertPhase2(Klass klass) {
   Assert.that(translationStrategy != BY_METHOD);
   convert(klass);
   if (klass.getState() < Klass.STATE_CONVERTED) {
     if (!VM
         .isVerbose()) { // "squawk -verbose" will show the class names as it finishes loading
                         // them, which is progress enough
       traceProgress();
     }
     lastClassNameStack.push(klass.getName());
     ClassFile classFile = getClassFile(klass);
     classFile.convertPhase2(this, false);
     classFiles.remove(klass.getName());
     lastClassNameStack.pop();
   }
 }
Example #16
0
 /**
  * Tests two given types to ensure that they are both {@link Klass#isSquawkPrimitive() Squawk
  * primitives} or both not Squawk primitives. If they are both Squawk primitives, then they must
  * be exactly the same type. This enforces the constraint that Squawk primitive values cannot be
  * assigned to or compared with any other type.
  *
  * @param type1 the first type to compare
  * @param type2 the second type to compare
  */
 public void verifyUseOfSquawkPrimitive(Klass type1, Klass type2) {
   if (type1.isSquawkPrimitive() || type2.isSquawkPrimitive()) {
     if (type1 != type2) {
       // Offsets are implemented as Words
       //                if (type1.getClassID() + type2.getClassID() != CID.UWORD + CID.OFFSET) {
       String type = type1.getName();
       throw codeParser.verifyError(
           type
               + " values can only be written to or compared with other "
               + type
               + " values, not with "
               + type2.getName());
       //                }
     }
   }
 }
Example #17
0
 /**
  * Returns the runtime class of an object. That <tt>Class</tt> object is the object that is locked
  * by <tt>static synchronized</tt> methods of the represented class.
  *
  * @return the object of type <code>Class</code> that represents the runtime class of the object.
  */
 public final Class getClass() {
   Klass klass = GC.getKlass(this);
   if (klass == Klass.STRING_OF_BYTES) {
     klass = Klass.STRING;
   }
   return Klass.asClass(klass);
 }
Example #18
0
 /**
  * Gets the type of the value at a given index on the operand stack.
  *
  * @param index the operand stack index
  * @return the type of the value at index <code>index</code> on the operand stack
  */
 public Klass getStackTypeAt(int index) {
   Assert.that(index < sp, "index out of bounds");
   if (stack[index] == null) {
     return Klass.getSecondWordType(stack[index - 1].getType());
   } else {
     return stack[index].getType();
   }
 }
Example #19
0
 /**
  * Returns interfaces directly implemented by this type.
  *
  * @return a List of the interfaces directly implemented by this type
  */
 @SuppressWarnings("unchecked")
 public List getInterfaces() throws IOException, SDWPException {
   Klass[] interfaces = klass.getInterfaces();
   List list = new ArrayList(interfaces.length);
   for (int i = 0; i != interfaces.length; ++i) {
     list.add(ptm.lookup(interfaces[i], true));
   }
   return list;
 }
 public boolean implementsInterface(Klass k) {
   if (Assert.ASSERTS_ENABLED) {
     Assert.that(k.isInterface(), "should not reach here");
   }
   ObjArray interfaces = getTransitiveInterfaces();
   final int len = (int) interfaces.getLength();
   for (int i = 0; i < len; i++) {
     if (interfaces.getObjAt(i).equals(k)) return true;
   }
   return false;
 }
Example #21
0
 /**
  * Verify that a local variable index for a given type is not out of bounds.
  *
  * @param type the type of the local variable at <code>index</code> in the local variables array
  * @param index the index of a local variable
  */
 public void verifyLocalVariableIndex(Klass type, int index) {
   if (index < 0) {
     throw codeParser.verifyError("invalid local variable index");
   }
   if (type.isDoubleWord()) {
     index++;
   }
   if (index >= localTypes.length) {
     throw codeParser.verifyError("invalid local variable index");
   }
 }
Example #22
0
 public void iterateFields(OopVisitor visitor, boolean doVMFields) {
   super.iterateFields(visitor, doVMFields);
   if (doVMFields) {
     visitor.doCInt(dimension, true);
     visitor.doOop(higherDimension, true);
     visitor.doOop(lowerDimension, true);
     visitor.doCInt(vtableLen, true);
     visitor.doCInt(allocSize, true);
     visitor.doOop(componentMirror, true);
   }
 }
Example #23
0
 /**
  * Returns a list containing each {@link Method} declared directly in this type. Inherited methods
  * are not included. Constructors, the initialization method if any, and any synthetic methods
  * created by the compiler are included in the list.
  *
  * <p>For arrays and primitive classes, the returned list is always empty.
  *
  * @return a list {@link Method} objects; the list has length 0 if no methods exist.
  */
 public List getMethods() {
   if (methods == null) {
     if (klass.isArray()) {
       methods = Collections.EMPTY_LIST;
     } else {
       methods = new ArrayList();
       addMethods(methods, true);
       addMethods(methods, false);
     }
   }
   return methods;
 }
Example #24
0
 boolean computeSubtypeOf(Klass k) {
   // An array is a subtype of Serializable, Clonable, and Object
   Symbol name = k.getName();
   if (name != null
       && (name.equals(javaIoSerializableName())
           || name.equals(javaLangCloneableName())
           || name.equals(javaLangObjectName()))) {
     return true;
   } else {
     return false;
   }
 }
Example #25
0
  /** {@inheritDoc} */
  public void convert(Klass klass) {
    lastClassNameStack.push(klass.getName());
    int state = klass.getState();
    if (state < Klass.STATE_CONVERTING) {
      if (klass.isArray()) {
        convert(Klass.OBJECT);
        klass.changeState(Klass.STATE_CONVERTED);
      } else {
        traceProgress();

        ClassFile classFile = getClassFile(klass);
        classFile.convertPhase1(this, translationStrategy != BY_METHOD);
        if (klass.hasGlobalStatics()) {
          // record globals now.
          recordGlobalStatics(klass);
        }

        if (translationStrategy == BY_METHOD || translationStrategy == BY_CLASS) {
          // if NOT inlining, then generate squawk code now.
          classFile.convertPhase2(this, translationStrategy == BY_METHOD);
          classFiles.remove(klass.getName());
        }
      }
    }
    lastClassNameStack.pop();
  }
Example #26
0
  /**
   * Merges the current state of the operand stack into the saved state at a control flow target.
   * This method also verifies that the current state of the operand stack matches the expected
   * state of the operand stack at the target as pecified by a stack map entry.
   *
   * @param target the target encapsulting the merged state of the operand stack at a distinct
   *     address
   * @param replaceWithTarget if true, then the current state of the operand stack is updated to
   *     reflect the state recorded in the stack map entry
   */
  public void mergeStack(Target target, boolean replaceWithTarget) {
    Klass[] recordedTypes = target.getStack();

    /*
     * Fail if the map sp is different
     */
    if (recordedTypes.length != getStackSize()) {
      throw codeParser.verifyError("size of recorded and derived stack differs");
    }

    /*
     * Check the stack items
     */
    for (int r = 0, d = 0; r < recordedTypes.length; ++r, ++d) {
      Klass recordedType = recordedTypes[r];
      Klass derivedType = getStackTypeAt(d);
      if (!recordedType.isAssignableFrom(derivedType)) {

        // Interfaces are treated like java.lang.Object in the verifier according to the CLDC spec.
        if (!recordedType.isInterface() || !Klass.OBJECT.isAssignableFrom(derivedType)) {
          throw codeParser.verifyError(
              "invalid type on operand stack @ "
                  + d
                  + ": expected "
                  + recordedType
                  + ", received "
                  + derivedType);
        }
      }
    }

    /*
     * Merge the instructions on the stack
     */
    target.merge(this);

    if (replaceWithTarget) {
      resetStack(target, false);
    }
  }
Example #27
0
  /**
   * Pushes a value to the operand stack.
   *
   * @param producer the instruction producing the value being pushed
   */
  public void push(StackProducer producer) {
    Klass type = producer.getType();
    Assert.that(type != Klass.VOID);

    /*
     * Check for overflow and push the producer.
     */
    if (sp == maxStack) {
      throw codeParser.verifyError("operand stack overflow");
    }
    stack[sp++] = producer;

    /*
     * For long and double check for overflow and then add a null word to the stack.
     */
    if (type.isDoubleWord()) {
      if (sp == maxStack) {
        throw codeParser.verifyError("operand stack overflow");
      }
      stack[sp++] = null;
    }
  }
Example #28
0
  /** Load and converts the closure of classes in the current suite. */
  public void computeClosure() {
    boolean changed = true;
    while (changed) {
      changed = false;
      for (int cno = 0; cno < suite.getClassCount(); cno++) {
        Klass klass = suite.getKlass(cno);

        if (klass == null) {
          continue; // if not floats, or if deferred errors, there can be some missing classes
        }

        if (klass.getState() < Klass.STATE_LOADED) {
          load(klass);
          changed = true;
        }
        if (klass.getState() < Klass.STATE_CONVERTING) {
          convert(klass);
          changed = true;
        }
      }
    }
  }
Example #29
0
 /**
  * Traces a type on the operand stack or in a local variable.
  *
  * @param type the type to trace
  * @param prefix the prefix to use if <code>isDerived</code> is true otherwise a prefix of spaces
  *     the same length as <code>prefix</code> is used instead
  * @param isDerived specifies if this a type derived by the verifer or is specified by a stack map
  *     entry
  */
 private void traceType(Klass type, String prefix, boolean isDerived) {
   if (Translator.TRACING_ENABLED) {
     if (!isDerived) {
       char[] spaces = new char[prefix.length()];
       Arrays.fill(spaces, ' ');
       Tracer.trace(new String(spaces));
     } else {
       Tracer.trace(prefix);
     }
     String name = (type == null ? "-T-" : type.getInternalName());
     if (isDerived) {
       Tracer.traceln(" " + name);
     } else {
       Tracer.traceln("{" + name + "}");
     }
   }
 }
Example #30
0
  /**
   * Emulates loading a value of a given type from a local variable.
   *
   * @param index the index of the local variable being loaded from
   * @param localType the expected type of the variable from which the value is loaded
   * @return the variable from which the value is loaded
   */
  public Local load(int index, Klass localType) {
    verifyLocalVariableIndex(localType, index);
    Klass derivedType = localTypes[index];
    if (!localType.isAssignableFrom(derivedType)) {
      throw codeParser.verifyError("incompatible type in local variable");
    }

    if (localType.isDoubleWord()) {
      Klass secondWordType = Klass.getSecondWordType(localType);
      if (!secondWordType.isAssignableFrom(localTypes[index + 1])) {
        throw codeParser.verifyError("incompatible type in local variable");
      }
    }

    if (derivedType.isSquawkPrimitive()) {
      localType = derivedType;
    }
    return allocateLocal(localType, index);
  }