示例#1
0
  private void doConvertAndCast(ClassNode targetType, boolean coerce) {
    int size = stack.size();
    throwExceptionForNoStackElement(size, targetType, coerce);

    ClassNode top = stack.get(size - 1);
    targetType = targetType.redirect();
    if (targetType == top) return;

    if (coerce) {
      controller.getInvocationWriter().coerce(top, targetType);
      return;
    }

    boolean primTarget = ClassHelper.isPrimitiveType(targetType);
    boolean primTop = ClassHelper.isPrimitiveType(top);

    if (primTop && primTarget) {
      // here we box and unbox to get the goal type
      if (convertPrimitive(top, targetType)) {
        replace(targetType);
        return;
      }
      box();
    } else if (primTop) {
      // top is primitive, target is not
      // so box and do groovy cast
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    } else if (primTarget) {
      // top is not primitive so unbox
      // leave that BH#doCast later
    } else {
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    }

    MethodVisitor mv = controller.getMethodVisitor();
    if (primTarget
        && !ClassHelper.boolean_TYPE.equals(targetType)
        && !primTop
        && ClassHelper.getWrapper(targetType).equals(top)) {
      BytecodeHelper.doCastToPrimitive(mv, top, targetType);
    } else {
      top = stack.get(size - 1);
      if (!WideningCategories.implementsInterfaceOrSubclassOf(top, targetType)) {
        BytecodeHelper.doCast(mv, targetType);
      }
    }
    replace(targetType);
  }
 private void printTypeName(PrintWriter out, ClassNode type) {
   if (ClassHelper.isPrimitiveType(type)) {
     if (type == ClassHelper.boolean_TYPE) {
       out.print("boolean");
     } else if (type == ClassHelper.char_TYPE) {
       out.print("char");
     } else if (type == ClassHelper.int_TYPE) {
       out.print("int");
     } else if (type == ClassHelper.short_TYPE) {
       out.print("short");
     } else if (type == ClassHelper.long_TYPE) {
       out.print("long");
     } else if (type == ClassHelper.float_TYPE) {
       out.print("float");
     } else if (type == ClassHelper.double_TYPE) {
       out.print("double");
     } else if (type == ClassHelper.byte_TYPE) {
       out.print("byte");
     } else {
       out.print("void");
     }
   } else {
     String name = type.getName();
     // check for an alias
     ClassNode alias = currentModule.getImportType(name);
     if (alias != null) name = alias.getName();
     out.print(name.replace('$', '.'));
   }
 }
示例#3
0
 /**
  * ensure last marked parameter on the stack is a primitive boolean if mark==stack size, we assume
  * an empty expression or statement. was used and we will use the value given in emptyDefault as
  * boolean if mark==stack.size()-1 the top element will be cast to boolean using Groovy truth. In
  * other cases we throw a GroovyBugError
  */
 public void castToBool(int mark, boolean emptyDefault) {
   int size = stack.size();
   MethodVisitor mv = controller.getMethodVisitor();
   if (mark == size) {
     // no element, so use emptyDefault
     if (emptyDefault) {
       mv.visitIntInsn(BIPUSH, 1);
     } else {
       mv.visitIntInsn(BIPUSH, 0);
     }
     stack.add(null);
   } else if (mark == stack.size() - 1) {
     ClassNode last = stack.get(size - 1);
     // nothing to do in that case
     if (last == ClassHelper.boolean_TYPE) return;
     // not a primitive type, so call booleanUnbox
     if (!ClassHelper.isPrimitiveType(last)) {
       controller.getInvocationWriter().castNonPrimitiveToBool(last);
     } else {
       primitive2b(mv, last);
     }
   } else {
     throw new GroovyBugError(
         "operand stack contains " + stack.size() + " elements, but we expected only " + mark);
   }
   stack.set(mark, ClassHelper.boolean_TYPE);
 }
 private boolean isKnownImmutableClass(ClassNode fieldType, List<String> knownImmutableClasses) {
   if (!fieldType.isResolved()) return false;
   return fieldType.isEnum()
       || ClassHelper.isPrimitiveType(fieldType)
       || fieldType.getAnnotations(MY_TYPE).size() != 0
       || inImmutableList(fieldType.getName())
       || knownImmutableClasses.contains(fieldType.getName());
 }
示例#5
0
 public ClassNode getPlainNodeReference() {
   if (ClassHelper.isPrimitiveType(this)) return this;
   ClassNode n = new ClassNode(name, modifiers, superClass, null, null);
   n.isPrimaryNode = false;
   n.setRedirect(redirect());
   if (isArray()) {
     n.componentType = redirect().getComponentType();
   }
   return n;
 }
 /**
  * Visits a class literal. If the type of the classnode is a primitive type, the generated
  * bytecode will be a GETSTATIC Integer.TYPE. If the classnode is not a primitive type, we will
  * generate a LDC instruction.
  */
 public static void visitClassLiteral(MethodVisitor mv, ClassNode classNode) {
   if (ClassHelper.isPrimitiveType(classNode)) {
     mv.visitFieldInsn(
         GETSTATIC,
         getClassInternalName(ClassHelper.getWrapper(classNode)),
         "TYPE",
         "Ljava/lang/Class;");
   } else {
     mv.visitLdcInsn(org.objectweb.asm.Type.getType(getTypeDescription(classNode)));
   }
 }
 public static void doCast(MethodVisitor mv, ClassNode type) {
   if (type == ClassHelper.OBJECT_TYPE) return;
   if (ClassHelper.isPrimitiveType(type) && type != ClassHelper.VOID_TYPE) {
     unbox(mv, type);
   } else {
     mv.visitTypeInsn(
         CHECKCAST,
         type.isArray()
             ? BytecodeHelper.getTypeDescription(type)
             : BytecodeHelper.getClassInternalName(type.getName()));
   }
 }
示例#8
0
 public ClassNode box() {
   MethodVisitor mv = controller.getMethodVisitor();
   int size = stack.size();
   ClassNode type = stack.get(size - 1);
   if (ClassHelper.isPrimitiveType(type) && ClassHelper.VOID_TYPE != type) {
     ClassNode wrapper = ClassHelper.getWrapper(type);
     BytecodeHelper.doCastToWrappedType(mv, type, wrapper);
     type = wrapper;
   } // else nothing to box
   stack.set(size - 1, type);
   return type;
 }
 private static void writeGenericsBoundType(
     StringBuffer ret, ClassNode printType, boolean writeInterfaceMarker) {
   if (writeInterfaceMarker && printType.isInterface()) ret.append(":");
   if (printType.equals(ClassHelper.OBJECT_TYPE) && printType.getGenericsTypes() != null) {
     ret.append("T");
     ret.append(printType.getGenericsTypes()[0].getName());
     ret.append(";");
   } else {
     ret.append(getTypeDescription(printType, false));
     addSubTypes(ret, printType.getGenericsTypes(), "<", ">");
     if (!ClassHelper.isPrimitiveType(printType)) ret.append(";");
   }
 }
  private void printDefaultValue(PrintWriter out, ClassNode type) {
    if (type.redirect() != ClassHelper.OBJECT_TYPE && type.redirect() != ClassHelper.boolean_TYPE) {
      out.print("(");
      printType(out, type);
      out.print(")");
    }

    if (ClassHelper.isPrimitiveType(type)) {
      if (type == ClassHelper.boolean_TYPE) {
        out.print("false");
      } else {
        out.print("0");
      }
    } else {
      out.print("null");
    }
  }
  private void printField(PrintWriter out, FieldNode fieldNode, boolean isInterface) {
    if ((fieldNode.getModifiers() & Opcodes.ACC_PRIVATE) != 0) return;
    printAnnotations(out, fieldNode);
    if (!isInterface) {
      printModifiers(out, fieldNode.getModifiers());
    }

    ClassNode type = fieldNode.getType();
    printType(out, type);

    out.print(" ");
    out.print(fieldNode.getName());
    if (isInterface || (fieldNode.getModifiers() & Opcodes.ACC_FINAL) != 0) {
      out.print(" = ");
      Expression valueExpr = fieldNode.getInitialValueExpression();
      if (valueExpr instanceof ConstantExpression) {
        valueExpr = Verifier.transformToPrimitiveConstantIfPossible((ConstantExpression) valueExpr);
      }
      if (valueExpr instanceof ConstantExpression
          && fieldNode.isStatic()
          && fieldNode.isFinal()
          && ClassHelper.isStaticConstantInitializerType(valueExpr.getType())
          && valueExpr.getType().equals(fieldNode.getType())) {
        // GROOVY-5150 : Initialize value with a dummy constant so that Java cross compiles
        // correctly
        if (ClassHelper.STRING_TYPE.equals(valueExpr.getType())) {
          out.print("\"" + escapeSpecialChars(valueExpr.getText()) + "\"");
        } else if (ClassHelper.char_TYPE.equals(valueExpr.getType())) {
          out.print("'" + valueExpr.getText() + "'");
        } else {
          ClassNode constantType = valueExpr.getType();
          out.print('(');
          printType(out, type);
          out.print(") ");
          out.print(valueExpr.getText());
          if (ClassHelper.Long_TYPE.equals(ClassHelper.getWrapper(constantType))) out.print('L');
        }
      } else if (ClassHelper.isPrimitiveType(type)) {
        String val = type == ClassHelper.boolean_TYPE ? "false" : "0";
        out.print("new " + ClassHelper.getWrapper(type) + "((" + type + ")" + val + ")");
      } else {
        out.print("null");
      }
    }
    out.println(";");
  }
示例#12
0
 /**
  * array types are special: eg.: String[]: classname: [Ljava/lang/String; int[]: [I
  *
  * @return the ASM type description
  */
 private static String getTypeDescription(ClassNode c, boolean end) {
   StringBuffer buf = new StringBuffer();
   ClassNode d = c;
   while (true) {
     if (ClassHelper.isPrimitiveType(d)) {
       char car;
       if (d == ClassHelper.int_TYPE) {
         car = 'I';
       } else if (d == ClassHelper.VOID_TYPE) {
         car = 'V';
       } else if (d == ClassHelper.boolean_TYPE) {
         car = 'Z';
       } else if (d == ClassHelper.byte_TYPE) {
         car = 'B';
       } else if (d == ClassHelper.char_TYPE) {
         car = 'C';
       } else if (d == ClassHelper.short_TYPE) {
         car = 'S';
       } else if (d == ClassHelper.double_TYPE) {
         car = 'D';
       } else if (d == ClassHelper.float_TYPE) {
         car = 'F';
       } else /* long */ {
         car = 'J';
       }
       buf.append(car);
       return buf.toString();
     } else if (d.isArray()) {
       buf.append('[');
       d = d.getComponentType();
     } else {
       buf.append('L');
       String name = d.getName();
       int len = name.length();
       for (int i = 0; i < len; ++i) {
         char car = name.charAt(i);
         buf.append(car == '.' ? '/' : car);
       }
       if (end) buf.append(';');
       return buf.toString();
     }
   }
 }
示例#13
0
 /**
  * array types are special: eg.: String[]: classname: [Ljava.lang.String; Object: classname:
  * java.lang.Object int[] : classname: [I unlike getTypeDescription '.' is not replaced by '/'. it
  * seems that makes problems for the class loading if '.' is replaced by '/'
  *
  * @return the ASM type description for class loading
  */
 public static String getClassLoadingTypeDescription(ClassNode c) {
   StringBuffer buf = new StringBuffer();
   boolean array = false;
   while (true) {
     if (c.isArray()) {
       buf.append('[');
       c = c.getComponentType();
       array = true;
     } else {
       if (ClassHelper.isPrimitiveType(c)) {
         buf.append(getTypeDescription(c));
       } else {
         if (array) buf.append('L');
         buf.append(c.getName());
         if (array) buf.append(';');
       }
       return buf.toString();
     }
   }
 }
示例#14
0
  /** load the constant on the operand stack. */
  public void pushConstant(ConstantExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    Object value = expression.getValue();
    ClassNode origType = expression.getType().redirect();
    ClassNode type = ClassHelper.getUnwrapper(origType);
    boolean boxing = origType != type;
    boolean asPrimitive = boxing || ClassHelper.isPrimitiveType(type);

    if (value == null) {
      mv.visitInsn(ACONST_NULL);
    } else if (boxing && value instanceof Boolean) {
      // special path for boxed boolean
      Boolean bool = (Boolean) value;
      String text = bool ? "TRUE" : "FALSE";
      mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", text, "Ljava/lang/Boolean;");
      boxing = false;
      type = origType;
    } else if (asPrimitive) {
      pushPrimitiveConstant(mv, value, type);
    } else if (value instanceof BigDecimal) {
      String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
      mv.visitTypeInsn(NEW, className);
      mv.visitInsn(DUP);
      mv.visitLdcInsn(value.toString());
      mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
    } else if (value instanceof BigInteger) {
      String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
      mv.visitTypeInsn(NEW, className);
      mv.visitInsn(DUP);
      mv.visitLdcInsn(value.toString());
      mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
    } else if (value instanceof String) {
      mv.visitLdcInsn(value);
    } else {
      throw new ClassGeneratorException(
          "Cannot generate bytecode for constant: " + value + " of type: " + type.getName());
    }

    push(type);
    if (boxing) box();
  }