public static void genInvokeXxxWithArray(ClassWriter cw, Method method) { MethodVisitor mv; mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", null, EXCEPTIONS); mv.visitCode(); BytecodeHelper helper = new BytecodeHelper(mv); Class callClass = method.getDeclaringClass(); boolean useInterface = callClass.isInterface(); String type = BytecodeHelper.getClassInternalName(callClass.getName()); String descriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes()); // make call if (Modifier.isStatic(method.getModifiers())) { genLoadParameters(2, mv, helper, method); mv.visitMethodInsn(Opcodes.INVOKESTATIC, type, method.getName(), descriptor); } else { mv.visitVarInsn(Opcodes.ALOAD, 1); helper.doCast(callClass); genLoadParameters(2, mv, helper, method); mv.visitMethodInsn((useInterface) ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, type, method.getName(), descriptor); } helper.box(method.getReturnType()); if (method.getReturnType() == void.class) { mv.visitInsn(Opcodes.ACONST_NULL); } mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); }
public static String getGenericsBounds(ClassNode type) { GenericsType[] genericsTypes = type.getGenericsTypes(); if (genericsTypes == null) return null; StringBuffer ret = new StringBuffer(100); if (type.isGenericsPlaceHolder()) { addSubTypes(ret, type.getGenericsTypes(), "", ""); } else { GenericsType gt = new GenericsType(type); writeGenericsBounds(ret, gt, false); } return ret.toString(); }
/** * box the primitive value on the stack * * @param type */ public void quickBoxIfNecessary(ClassNode type) { String descr = getTypeDescription(type); if (type == ClassHelper.boolean_TYPE) { boxBoolean(); } else if (ClassHelper.isPrimitiveType(type) && type != ClassHelper.VOID_TYPE) { ClassNode wrapper = ClassHelper.getWrapper(type); String internName = getClassInternalName(wrapper); mv.visitTypeInsn(NEW, internName); mv.visitInsn(DUP); if (type == ClassHelper.double_TYPE || type == ClassHelper.long_TYPE) { mv.visitInsn(DUP2_X2); mv.visitInsn(POP2); } else { mv.visitInsn(DUP2_X1); mv.visitInsn(POP2); } mv.visitMethodInsn(INVOKESPECIAL, internName, "<init>", "(" + descr + ")V"); } }
public static void genLoadParametersDirect(int argumentIndex, MethodVisitor mv, BytecodeHelper helper, Method method) { Class<?>[] parameters = method.getParameterTypes(); int size = parameters.length; for (int i = 0; i < size; i++) { mv.visitVarInsn(Opcodes.ALOAD, argumentIndex+i); // cast argument to parameter class, inclusive unboxing // for methods with primitive types Class type = parameters[i]; if (type.isPrimitive()) { helper.unbox(type); } else { helper.doCast(type); } } }
public void doCast(Class type) { if (type != Object.class) { if (type.isPrimitive() && type != Void.TYPE) { unbox(type); } else { mv.visitTypeInsn( CHECKCAST, type.isArray() ? getTypeDescription(type) : getClassInternalName(type.getName())); } } }
public static void genLoadParameters(int argumentIndex, MethodVisitor mv, BytecodeHelper helper, Method method) { Class<?>[] parameters = method.getParameterTypes(); int size = parameters.length; for (int i = 0; i < size; i++) { // unpack argument from Object[] mv.visitVarInsn(Opcodes.ALOAD, argumentIndex); helper.pushConstant(i); mv.visitInsn(Opcodes.AALOAD); // cast argument to parameter class, inclusive unboxing // for methods with primitive types Class type = parameters[i]; if (type.isPrimitive()) { helper.unbox(type); } else { helper.doCast(type); } } }
public void visit(MethodVisitor mv) { BytecodeHelper helper = new BytecodeHelper(mv); mv.visitVarInsn(ALOAD,0); Parameter[] para = oldMethod.getParameters(); Parameter[] goal = overridingMethod.getParameters(); for (int i = 0; i < para.length; i++) { helper.load(para[i].getType(), i+1); if (!para[i].getType().equals(goal[i].getType())) { helper.doCast(goal[i].getType()); } } mv.visitMethodInsn( INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(classNode), overridingMethod.getName(), BytecodeHelper.getMethodDescriptor(overridingMethod.getReturnType(), overridingMethod.getParameters())); helper.doReturn(oldMethod.getReturnType()); } }
/** * @param fldExp */ public void loadStaticField(FieldExpression fldExp) { FieldNode field = fldExp.getField(); boolean holder = field.isHolder() && !isInClosureConstructor(); ClassNode type = field.getType(); String ownerName = (field.getOwner().equals(classNode)) ? internalClassName : BytecodeHelper.getClassInternalName(field.getOwner()); if (holder) { mv.visitFieldInsn(GETSTATIC, ownerName, fldExp.getFieldName(), BytecodeHelper.getTypeDescription(type)); mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;"); } else { mv.visitFieldInsn(GETSTATIC, ownerName, fldExp.getFieldName(), BytecodeHelper.getTypeDescription(type)); if (ClassHelper.isPrimitiveType(type)) { helper.box(type); } else { } } }
public static String getGenericsMethodSignature(MethodNode node) { GenericsType[] generics = node.getGenericsTypes(); Parameter[] param = node.getParameters(); ClassNode returnType = node.getReturnType(); if (generics == null && !hasGenerics(param) && returnType.getGenericsTypes() == null) return null; StringBuffer ret = new StringBuffer(100); getGenericsTypeSpec(ret, generics); GenericsType[] paramTypes = new GenericsType[param.length]; for (int i = 0; i < param.length; i++) { ClassNode pType = param[i].getType(); if (pType.getGenericsTypes() == null || !pType.isGenericsPlaceHolder()) { paramTypes[i] = new GenericsType(pType); } else { paramTypes[i] = pType.getGenericsTypes()[0]; } } addSubTypes(ret, paramTypes, "(", ")"); if (returnType.isGenericsPlaceHolder()) { addSubTypes(ret, returnType.getGenericsTypes(), "", ""); } else { writeGenericsBounds(ret, new GenericsType(returnType), false); } return ret.toString(); }
public void visit(MethodVisitor mv) { if (field.isStatic()) { mv.visitFieldInsn(GETSTATIC, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType())); } else { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType())); } final BytecodeHelper helper = new BytecodeHelper(mv); helper.doReturn(field.getType()); } });
public void visit(MethodVisitor mv) { final BytecodeHelper helper = new BytecodeHelper(mv); if (field.isStatic()) { helper.load(field.getType(), 0); mv.visitFieldInsn(PUTSTATIC, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType())); } else { mv.visitVarInsn(ALOAD, 0); helper.load(field.getType(), 1); mv.visitFieldInsn(PUTFIELD, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType())); } mv.visitInsn(RETURN); } });
public void storeStaticField(FieldExpression expression) { FieldNode field = expression.getField(); boolean holder = field.isHolder() && !isInClosureConstructor(); ClassNode type = field.getType(); String ownerName = (field.getOwner().equals(classNode)) ? internalClassName : helper.getClassInternalName(field.getOwner()); if (holder) { mv.visitFieldInsn(GETSTATIC, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(type)); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V"); } else { helper.doCast(type); mv.visitFieldInsn(PUTSTATIC, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(type)); } }
this.classNode = classNode; this.outermostClass = null; this.internalClassName = BytecodeHelper.getClassInternalName(classNode); this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass()); classNode.getModifiers(), internalClassName, BytecodeHelper.getGenericsSignature(classNode), internalBaseClassName, BytecodeHelper.getClassInternalNames(classNode.getInterfaces()) ); cv.visitSource(sourceFile, null); ClassNode innerClass = (ClassNode) iter.next(); String innerClassName = innerClass.getName(); String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassName);
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { lineNumber = -1; columnNumber = -1; Parameter[] parameters = node.getParameters(); String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters); String signature = BytecodeHelper.getGenericsMethodSignature(node); int modifiers = node.getModifiers(); if (isVargs(node.getParameters())) modifiers |= Opcodes.ACC_VARARGS; mv = cv.visitMethod(modifiers, node.getName(), methodType, signature, buildExceptions(node.getExceptions())); mv = new MyMethodAdapter(); visitAnnotations(node, mv); for (int i = 0; i < parameters.length; i++) { visitParameterAnnotations(parameters[i], i, mv); } helper = new BytecodeHelper(mv); if (classNode.isAnnotationDefinition()) { visitAnnotationDefault(node, mv); } else if (!node.isAbstract()) { Statement code = node.getCode(); // fast path for getter/setters etc. if (code instanceof BytecodeSequence && ((BytecodeSequence)code).getInstructions().size() == 1 && ((BytecodeSequence)code).getInstructions().get(0) instanceof BytecodeInstruction) { ((BytecodeInstruction)((BytecodeSequence)code).getInstructions().get(0)).visit(mv); } else{ visitStdMethod(node, isConstructor, parameters, code); } mv.visitMaxs(0, 0); } mv.visitEnd(); }
/** * load the value of the variable on the operand stack. unbox it if it's a reference * * @param variable */ public void loadVar(Variable variable) { int index = variable.getIndex(); if (variable.isHolder()) { mv.visitVarInsn(ALOAD, index); mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;"); } else { load(variable); if (variable != Variable.THIS_VARIABLE && variable != Variable.SUPER_VARIABLE) { box(variable.getType()); } } }
private void addGeneratedClosureConstructorCall(ConstructorCallExpression call) { mv.visitVarInsn(ALOAD, 0); ClassNode callNode = classNode.getSuperClass(); TupleExpression arguments = (TupleExpression) call.getArguments(); if (arguments.getExpressions().size()!=2) throw new GroovyBugError("expected 2 arguments for closure constructor super call, but got"+arguments.getExpressions().size()); arguments.getExpression(0).visit(this); arguments.getExpression(1).visit(this); Parameter p = new Parameter(ClassHelper.OBJECT_TYPE,"_p"); String descriptor = helper.getMethodDescriptor(ClassHelper.VOID_TYPE, new Parameter[]{p,p}); mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(callNode), "<init>", descriptor); }
private static void writeGenericsBoundType(StringBuffer ret, ClassNode printType, boolean writeInterfaceMarker) { if (writeInterfaceMarker && printType.isInterface()) ret.append(":"); ret.append(getTypeDescription(printType, false)); addSubTypes(ret, printType.getGenericsTypes(), "<", ">"); if (!ClassHelper.isPrimitiveType(printType)) ret.append(";"); }
/** * Generates the bytecode to autobox the current value on the stack */ public void box(Class type) { if (ReflectionCache.getCachedClass(type).isPrimitive && type != void.class) { String returnString = "(" + getTypeDescription(type) + ")Ljava/lang/Object;"; mv.visitMethodInsn(INVOKESTATIC, getClassInternalName(DefaultTypeTransformation.class.getName()), "box", returnString); } }
/** * initializes this class for a MethodNode. This method will * automatically define varibales for the method parameters * and will create references if needed. the created variables * can be get by getVariable * */ protected void init(VariableScope el, Parameter[] parameters, MethodVisitor mv, ClassNode cn) { if (!clear) throw new GroovyBugError("CompileStack#init called without calling clear before"); clear=false; pushVariableScope(el); this.mv = mv; this.helper = new BytecodeHelper(mv); defineMethodVariables(parameters,el.isInStaticContext()); this.className = BytecodeHelper.getTypeDescription(cn); }