Search in sources :

Example 11 with MethodNode

use of org.jetbrains.org.objectweb.asm.tree.MethodNode in project kotlin by JetBrains.

the class InlineCodegen method inlineCall.

@NotNull
private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap) {
    assert delayedHiddenWriting == null : "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'";
    DefaultSourceMapper defaultSourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
    defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber()));
    MethodNode node = nodeAndSmap.getNode();
    ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
    generateClosuresBodies();
    //through generation captured parameters will be added to invocationParamBuilder
    putClosureParametersOnStack();
    addInlineMarker(codegen.v, true);
    Parameters parameters = invocationParamBuilder.buildParameters();
    InliningContext info = new RootInliningContext(expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings);
    MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText(), createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(), isInlineOnly(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null);
    //with captured
    LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
    MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
    //hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
    adapter.visitInsn(Opcodes.NOP);
    InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
    result.getReifiedTypeParametersUsages().mergeAll(reificationResult);
    CallableMemberDescriptor descriptor = getLabelOwnerDescriptor(codegen.getContext());
    final Set<String> labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor);
    LabelOwner labelOwner = new LabelOwner() {

        @Override
        public boolean isMyLabel(@NotNull String name) {
            return labels.contains(name);
        }
    };
    List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null);
    generateAndInsertFinallyBlocks(adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index);
    removeStaticInitializationTrigger(adapter);
    if (!InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) {
        InlineCodegenUtil.removeFinallyMarkers(adapter);
    }
    adapter.accept(new MethodBodyVisitor(codegen.v));
    addInlineMarker(codegen.v, false);
    defaultSourceMapper.setCallSiteMarker(null);
    return result;
}
Also used : DeserializedCallableMemberDescriptor(org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor) NotNull(org.jetbrains.annotations.NotNull) MethodNode(org.jetbrains.org.objectweb.asm.tree.MethodNode) NotNull(org.jetbrains.annotations.NotNull)

Example 12 with MethodNode

use of org.jetbrains.org.objectweb.asm.tree.MethodNode in project kotlin by JetBrains.

the class InlineCodegen method generateAndInsertFinallyBlocks.

private void generateAndInsertFinallyBlocks(@NotNull MethodNode intoNode, @NotNull List<MethodInliner.PointForExternalFinallyBlocks> insertPoints, int offsetForFinallyLocalVar) {
    if (!codegen.hasFinallyBlocks())
        return;
    Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints = new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>();
    for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) {
        extensionPoints.put(insertPoint.beforeIns, insertPoint);
    }
    DefaultProcessor processor = new DefaultProcessor(intoNode, offsetForFinallyLocalVar);
    int curFinallyDepth = 0;
    AbstractInsnNode curInstr = intoNode.instructions.getFirst();
    while (curInstr != null) {
        processor.processInstruction(curInstr, true);
        if (InlineCodegenUtil.isFinallyStart(curInstr)) {
            //TODO depth index calc could be more precise
            curFinallyDepth = getConstant(curInstr.getPrevious());
        }
        MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr);
        if (extension != null) {
            Label start = new Label();
            MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode();
            finallyNode.visitLabel(start);
            ExpressionCodegen finallyCodegen = new ExpressionCodegen(finallyNode, codegen.getFrameMap(), codegen.getReturnType(), codegen.getContext(), codegen.getState(), codegen.getParentCodegen());
            finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.getBlockStackElements(), curFinallyDepth);
            FrameMap frameMap = finallyCodegen.getFrameMap();
            FrameMap.Mark mark = frameMap.mark();
            int marker = -1;
            Set<LocalVarNodeWrapper> intervals = processor.getLocalVarsMetaInfo().getCurrentIntervals();
            for (LocalVarNodeWrapper interval : intervals) {
                marker = Math.max(interval.getNode().index + 1, marker);
            }
            while (frameMap.getCurrentSize() < Math.max(processor.getNextFreeLocalIndex(), offsetForFinallyLocalVar + marker)) {
                frameMap.enterTemp(Type.INT_TYPE);
            }
            finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType, extension.finallyIntervalEnd.getLabel());
            //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
            InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr);
            SimpleInterval splitBy = new SimpleInterval((LabelNode) start.info, extension.finallyIntervalEnd);
            processor.getTryBlocksMetaInfo().splitCurrentIntervals(splitBy, true);
            //processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
            mark.dropTo();
        }
        curInstr = curInstr.getNext();
    }
    processor.substituteTryBlockNodes(intoNode);
//processor.substituteLocalVarTable(intoNode);
}
Also used : Label(org.jetbrains.org.objectweb.asm.Label) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) MethodNode(org.jetbrains.org.objectweb.asm.tree.MethodNode)

Example 13 with MethodNode

use of org.jetbrains.org.objectweb.asm.tree.MethodNode in project kotlin by JetBrains.

the class InlineCodegen method doCreateMethodNodeFromSource.

@NotNull
private static SMAPAndMethodNode doCreateMethodNodeFromSource(@NotNull FunctionDescriptor callableDescriptor, @NotNull JvmMethodSignature jvmSignature, @NotNull ExpressionCodegen codegen, @NotNull CodegenContext context, boolean callDefault, @NotNull GenerationState state, @NotNull Method asmMethod) {
    PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
    if (!(element instanceof KtNamedFunction || element instanceof KtPropertyAccessor)) {
        throw new IllegalStateException("Couldn't find declaration for function " + callableDescriptor);
    }
    KtDeclarationWithBody inliningFunction = (KtDeclarationWithBody) element;
    MethodNode node = new MethodNode(InlineCodegenUtil.API, getMethodAsmFlags(callableDescriptor, context.getContextKind(), state) | (callDefault ? Opcodes.ACC_STATIC : 0), asmMethod.getName(), asmMethod.getDescriptor(), null, null);
    //for maxLocals calculation
    MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
    CodegenContext parentContext = context.getParentContext();
    assert parentContext != null : "Context has no parent: " + context;
    MethodContext methodContext = parentContext.intoFunction(callableDescriptor);
    SMAP smap;
    if (callDefault) {
        Type implementationOwner = state.getTypeMapper().mapImplementationOwner(callableDescriptor);
        FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), inliningFunction, (FieldOwnerContext) methodContext.getParentContext(), implementationOwner.getInternalName());
        if (!(element instanceof KtNamedFunction)) {
            throw new IllegalStateException("Propertiy accessors with default parameters not supported " + callableDescriptor);
        }
        FunctionCodegen.generateDefaultImplBody(methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, (KtNamedFunction) inliningFunction, parentCodegen, asmMethod);
        smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
    } else {
        smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction, jvmSignature, codegen, null);
    }
    maxCalcAdapter.visitMaxs(-1, -1);
    maxCalcAdapter.visitEnd();
    return new SMAPAndMethodNode(node, smap);
}
Also used : MethodVisitor(org.jetbrains.org.objectweb.asm.MethodVisitor) Type(org.jetbrains.org.objectweb.asm.Type) KotlinType(org.jetbrains.kotlin.types.KotlinType) MethodNode(org.jetbrains.org.objectweb.asm.tree.MethodNode) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 14 with MethodNode

use of org.jetbrains.org.objectweb.asm.tree.MethodNode in project kotlin by JetBrains.

the class TrustAllX509TrustManagerDetector method checkClass.

// ---- Implements ClassScanner ----
// Only used for libraries where we have to analyze bytecode
@Override
@SuppressWarnings("rawtypes")
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    if (!context.isFromClassLibrary()) {
        // Non-library code checked at the AST level
        return;
    }
    if (!classNode.interfaces.contains("javax/net/ssl/X509TrustManager")) {
        return;
    }
    List methodList = classNode.methods;
    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;
        if ("checkServerTrusted".equals(method.name) || "checkClientTrusted".equals(method.name)) {
            InsnList nodes = method.instructions;
            // Stays true if method doesn't perform any "real"
            boolean emptyMethod = true;
            // operations
            for (int i = 0, n = nodes.size(); i < n; i++) {
                // Future work: Improve this check to be less sensitive to irrelevant
                // instructions/statements/invocations (e.g. System.out.println) by
                // looking for calls that could lead to a CertificateException being
                // thrown, e.g. throw statement within the method itself or invocation
                // of another method that may throw a CertificateException, and only
                // reporting an issue if none of these calls are found. ControlFlowGraph
                // may be useful here.
                AbstractInsnNode instruction = nodes.get(i);
                int type = instruction.getType();
                if (type != AbstractInsnNode.LABEL && type != AbstractInsnNode.LINE && !(type == AbstractInsnNode.INSN && instruction.getOpcode() == Opcodes.RETURN)) {
                    emptyMethod = false;
                    break;
                }
            }
            if (emptyMethod) {
                Location location = context.getLocation(method, classNode);
                context.report(ISSUE, location, getErrorMessage(method.name));
            }
        }
    }
}
Also used : MethodNode(org.jetbrains.org.objectweb.asm.tree.MethodNode) List(java.util.List) InsnList(org.jetbrains.org.objectweb.asm.tree.InsnList) InsnList(org.jetbrains.org.objectweb.asm.tree.InsnList) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) Location(com.android.tools.klint.detector.api.Location)

Example 15 with MethodNode

use of org.jetbrains.org.objectweb.asm.tree.MethodNode in project kotlin by JetBrains.

the class ClassContext method report.

/**
     * Reports an issue.
     * <p>
     * Detectors should only call this method if an error applies to the whole class
     * scope and there is no specific method or field that applies to the error.
     * If so, use
     * {@link #report(Issue, MethodNode, AbstractInsnNode, Location, String)} or
     * {@link #report(Issue, FieldNode, Location, String)}, such that
     * suppress annotations are checked.
     *
     * @param issue the issue to report
     * @param location the location of the issue, or null if not known
     * @param message the message for this warning
     */
@Override
public void report(@NonNull Issue issue, @NonNull Location location, @NonNull String message) {
    if (mDriver.isSuppressed(issue, mClassNode)) {
        return;
    }
    ClassNode curr = mClassNode;
    while (curr != null) {
        ClassNode prev = curr;
        curr = mDriver.getOuterClassNode(curr);
        if (curr != null) {
            if (prev.outerMethod != null) {
                // ASM API
                @SuppressWarnings("rawtypes") List methods = curr.methods;
                for (Object m : methods) {
                    MethodNode method = (MethodNode) m;
                    if (method.name.equals(prev.outerMethod) && method.desc.equals(prev.outerMethodDesc)) {
                        // class hierarchy)
                        if (method != null && mDriver.isSuppressed(issue, mClassNode, method, null)) {
                            return;
                        }
                        break;
                    }
                }
            }
            if (mDriver.isSuppressed(issue, curr)) {
                return;
            }
        }
    }
    super.report(issue, location, message);
}
Also used : ClassNode(org.jetbrains.org.objectweb.asm.tree.ClassNode) MethodNode(org.jetbrains.org.objectweb.asm.tree.MethodNode) List(java.util.List)

Aggregations

MethodNode (org.jetbrains.org.objectweb.asm.tree.MethodNode)16 NotNull (org.jetbrains.annotations.NotNull)8 List (java.util.List)4 ClassNode (org.jetbrains.org.objectweb.asm.tree.ClassNode)4 DeserializedCallableMemberDescriptor (org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor)3 MethodVisitor (org.jetbrains.org.objectweb.asm.MethodVisitor)3 AbstractInsnNode (org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)3 AnalyzerException (org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException)3 PsiElement (com.intellij.psi.PsiElement)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 KotlinType (org.jetbrains.kotlin.types.KotlinType)2 ClassReader (org.jetbrains.org.objectweb.asm.ClassReader)2 Method (org.jetbrains.org.objectweb.asm.commons.Method)2 InsnList (org.jetbrains.org.objectweb.asm.tree.InsnList)2 MethodInsnNode (org.jetbrains.org.objectweb.asm.tree.MethodInsnNode)2 Detector (com.android.tools.klint.detector.api.Detector)1 ClassScanner (com.android.tools.klint.detector.api.Detector.ClassScanner)1 Location (com.android.tools.klint.detector.api.Location)1 ProcessCanceledException (com.intellij.openapi.progress.ProcessCanceledException)1