/** Method invocation. */ public void visitInvokeInstruction(InvokeInstruction i) { Type[] argTypes = i.getArgumentTypes(cp); for (int j = 0; j < argTypes.length; j++) cv.registerCoupling(argTypes[j]); cv.registerCoupling(i.getReturnType(cp)); /* Measuring decision: measure overloaded methods separately */ cv.registerMethodInvocation(i.getClassName(cp), i.getMethodName(cp), argTypes); }
private FieldVisitor declareStaticField(ClassVisitor visitor, String name, Class<?> fieldClass) { return visitor.visitField( ACC_PRIVATE | ACC_FINAL | ACC_STATIC | ACC_SYNTHETIC, name, Type.getDescriptor(fieldClass), null, null); }
/** Visit the method's exception handlers. */ private void updateExceptionHandlers() { CodeExceptionGen[] handlers = mg.getExceptionHandlers(); /* Measuring decision: couple exceptions */ for (int i = 0; i < handlers.length; i++) { Type t = handlers[i].getCatchType(); if (t != null) cv.registerCoupling(t); } }
@Override public void visitEnd() { for (Map.Entry<Handle, Handle> entry : lambdaAccessToImplMethods.entrySet()) { Handle accessMethod = entry.getKey(); Handle implMethod = entry.getValue(); Bytecode.generateDelegateMethod(cv, ACC_STATIC | ACC_SYNTHETIC, accessMethod, implMethod); } super.visitEnd(); }
@Override public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, FOO, superName, interfaces); }
private MethodVisitor declareMethod( ClassVisitor visitor, String methodName, String methodDescriptor, String methodSignature, int access) { MethodVisitor methodVisitor = visitor.visitMethod(access, methodName, methodDescriptor, methodSignature, NO_EXCEPTIONS); methodVisitor.visitCode(); return methodVisitor; }
private void declareClass( ClassVisitor visitor, Collection<String> interfaceInternalNames, Type generatedType, Type superclassType) { visitor.visit( V1_6, ACC_PUBLIC, generatedType.getInternalName(), null, superclassType.getInternalName(), Iterables.toArray(interfaceInternalNames, String.class)); }
@Override public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { resetLambdaClassSequenceNumber(); this.classAccess = access; this.className = name; super.visit(version, access, name, signature, superName, interfaces); }
private void writeEqualsMethod(ClassVisitor cw, Type generatedType) { MethodVisitor methodVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "equals", EQUALS_METHOD_DESCRIPTOR, null, null); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitVarInsn(ALOAD, 1); Label notSameLabel = new Label(); methodVisitor.visitJumpInsn(IF_ACMPNE, notSameLabel); methodVisitor.visitInsn(ICONST_1); methodVisitor.visitInsn(IRETURN); methodVisitor.visitLabel(notSameLabel); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitTypeInsn(INSTANCEOF, MANAGED_INSTANCE_TYPE); Label notManagedInstanceLabel = new Label(); methodVisitor.visitJumpInsn(IFNE, notManagedInstanceLabel); methodVisitor.visitInsn(ICONST_0); methodVisitor.visitInsn(IRETURN); methodVisitor.visitLabel(notManagedInstanceLabel); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, generatedType.getInternalName(), "getBackingNode", GET_BACKING_NODE_METHOD_DESCRIPTOR, false); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitTypeInsn(CHECKCAST, MANAGED_INSTANCE_TYPE); methodVisitor.visitMethodInsn( INVOKEINTERFACE, MANAGED_INSTANCE_TYPE, "getBackingNode", GET_BACKING_NODE_METHOD_DESCRIPTOR, true); methodVisitor.visitMethodInsn( INVOKEINTERFACE, MUTABLE_MODEL_NODE_TYPE, "equals", EQUALS_METHOD_DESCRIPTOR, true); finishVisitingMethod(methodVisitor, Opcodes.IRETURN); }
/** Visit return instruction. */ public void visitReturnInstruction(ReturnInstruction i) { cv.registerCoupling(i.getType(cp)); }
private void declareField(ClassVisitor visitor, String name, Class<?> fieldClass) { visitor.visitField( ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, name, Type.getDescriptor(fieldClass), null, null); }
/** Constructor. */ MethodVisitor(MethodGen m, ClassVisitor c) { mg = m; cv = c; cp = mg.getConstantPool(); cm = cv.getMetrics(); }
/** Visit checklast instruction. */ public void visitCHECKCAST(CHECKCAST i) { cv.registerCoupling(i.getType(cp)); }
private void writeOuterInfo(@NotNull ClassVisitor visitor) { InlineCallSiteInfo info = inliningContext.getCallSiteInfo(); visitor.visitOuterClass( info.getOwnerClassName(), info.getFunctionName(), info.getFunctionDesc()); }
/** Field access. */ public void visitFieldInstruction(FieldInstruction i) { cv.registerFieldAccess(i.getClassName(cp), i.getFieldName(cp)); cv.registerCoupling(i.getFieldType(cp)); }
/** Array use. */ public void visitArrayInstruction(ArrayInstruction i) { cv.registerCoupling(i.getType(cp)); }
/** Local variable use. */ public void visitLocalVariableInstruction(LocalVariableInstruction i) { if (i.getOpcode() != Constants.IINC) cv.registerCoupling(i.getType(cp)); }
@NotNull public InlineResult doTransform( @NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) { final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>(); ClassBuilder classBuilder = createClassBuilder(); final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>(); reader.accept( new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) { @Override public void visit( int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name); super.visit(version, access, name, signature, superName, interfaces); } @Override public void visitInnerClass( @NotNull String name, String outerName, String innerName, int access) { innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access)); } @Override public MethodVisitor visitMethod( int access, @NotNull String name, @NotNull String desc, String signature, String[] exceptions) { MethodNode node = new MethodNode(access, name, desc, signature, exceptions); if (name.equals("<init>")) { if (constructor != null) throw new RuntimeException( "Lambda, SAM or anonymous object should have only one constructor"); constructor = node; } else { methodsToTransform.add(node); } return node; } @Override public FieldVisitor visitField( int access, @NotNull String name, @NotNull String desc, String signature, Object value) { addUniqueField(name); if (InlineCodegenUtil.isCapturedFieldName(name)) { return null; } else { return super.visitField(access, name, desc, signature, value); } } @Override public void visitSource(String source, String debug) { sourceInfo = source; debugInfo = debug; } @Override public void visitEnd() {} }, ClassReader.SKIP_FRAMES); if (!inliningContext.isInliningLambda) { if (debugInfo != null && !debugInfo.isEmpty()) { sourceMapper = SourceMapper.Companion.createFromSmap(SMAPParser.parse(debugInfo)); } else { // seems we can't do any clever mapping cause we don't know any about original class name sourceMapper = IdenticalSourceMapper.INSTANCE; } if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) { classBuilder.visitSource(sourceInfo, debugInfo); } } else { if (sourceInfo != null) { classBuilder.visitSource(sourceInfo, debugInfo); } sourceMapper = IdenticalSourceMapper.INSTANCE; } ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder(); ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder(); List<CapturedParamInfo> additionalFakeParams = extractParametersMappingAndPatchConstructor( constructor, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper); List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>(); for (MethodNode next : methodsToTransform) { MethodVisitor deferringVisitor = newMethod(classBuilder, next); InlineResult funResult = inlineMethodAndUpdateGlobalResult( anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false); Type returnType = Type.getReturnType(next.desc); if (!AsmUtil.isPrimitive(returnType)) { String oldFunReturnType = returnType.getInternalName(); String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType); if (newFunReturnType != null) { inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType); } } deferringMethods.add(deferringVisitor); } for (MethodVisitor method : deferringMethods) { method.visitEnd(); } generateConstructorAndFields( classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams); SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder); ClassVisitor visitor = classBuilder.getVisitor(); for (InnerClassNode node : innerClassNodes) { visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access); } writeOuterInfo(visitor); classBuilder.done(); anonymousObjectGen.setNewLambdaType(newLambdaType); return transformationResult; }
/** Visit an instanceof instruction. */ public void visitINSTANCEOF(INSTANCEOF i) { cv.registerCoupling(i.getType(cp)); }