public InlineCodegen( @NotNull ExpressionCodegen codegen, @NotNull GenerationState state, @NotNull SimpleFunctionDescriptor functionDescriptor, @NotNull JetElement callElement, @Nullable ReifiedTypeParameterMappings typeParameterMappings) { assert InlineUtil.isInline(functionDescriptor) : "InlineCodegen could inline only inline function: " + functionDescriptor; this.state = state; this.typeMapper = state.getTypeMapper(); this.codegen = codegen; this.callElement = callElement; this.functionDescriptor = functionDescriptor.getOriginal(); reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings); initialFrameSize = codegen.getFrameMap().getCurrentSize(); context = (MethodContext) getContext(functionDescriptor, state); jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind()); // TODO: implement AS_FUNCTION inline strategy InlineStrategy inlineStrategy = InlineUtil.getInlineStrategy(functionDescriptor); this.asFunctionInline = false; isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared( functionDescriptor, codegen.getContext(), state.getOutDirectory()); sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper(); reportIncrementalInfo( functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal()); }
private SMAPAndMethodNode generateLambdaBody(LambdaInfo info) { JetExpression declaration = info.getFunctionWithBodyOrCallableReference(); FunctionDescriptor descriptor = info.getFunctionDescriptor(); MethodContext parentContext = codegen.getContext(); MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor); JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor); Method asmMethod = jvmMethodSignature.getAsmMethod(); MethodNode methodNode = new MethodNode( InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind()), asmMethod.getName(), asmMethod.getDescriptor(), jvmMethodSignature.getGenericsSignature(), null); MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true); adapter.visitMaxs(-1, -1); return new SMAPAndMethodNode(methodNode, smap); }
public void removeFinallyMarkers(@NotNull MethodNode intoNode) { if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return; InsnList instructions = intoNode.instructions; AbstractInsnNode curInstr = instructions.getFirst(); while (curInstr != null) { if (InlineCodegenUtil.isFinallyMarker(curInstr)) { AbstractInsnNode marker = curInstr; // just to assert getConstant(marker.getPrevious()); curInstr = curInstr.getNext(); instructions.remove(marker.getPrevious()); instructions.remove(marker); continue; } curInstr = curInstr.getNext(); } }
public 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(); while (frameMap.getCurrentSize() < processor.getNextFreeLocalIndex()) { 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); }
private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) { MethodNode node = nodeAndSmap.getNode(); ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions); 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(functionDescriptor.getName().asString()), codegen.getContext(), callElement, codegen.getParentCodegen().getClassName(), reifiedTypeInliner); MethodInliner inliner = new MethodInliner( node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText(), createNestedSourceMapper(nodeAndSmap)); // 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 = codegen.getContext().getContextDescriptor(); 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.totalSize() + 1).value).index); removeFinallyMarkers(adapter); adapter.accept(new InliningInstructionAdapter(codegen.v)); addInlineMarker(codegen.v, false); return result; }