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;
}
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);
}
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);
}
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));
}
}
}
}
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);
}
Aggregations