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); }
public static boolean compileModules( @NotNull KotlinCoreEnvironment environment, @NotNull CompilerConfiguration configuration, @NotNull List<Module> chunk, @NotNull File directory, @Nullable File jarPath, @NotNull List<String> friendPaths, boolean jarRuntime) { Map<Module, ClassFileFactory> outputFiles = Maps.newHashMap(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ModuleVisibilityManager moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.getProject()); for (Module module : chunk) { moduleVisibilityManager.addModule(module); } for (String path : friendPaths) { moduleVisibilityManager.addFriendPath(path); } String targetDescription = "in targets [" + Joiner.on(", ") .join( Collections2.transform( chunk, new Function<Module, String>() { @Override public String apply(@Nullable Module input) { return input != null ? input.getModuleName() + "-" + input.getModuleType() : "<null>"; } })) + "] "; AnalysisResult result = analyze(environment, targetDescription); if (result == null) { return false; } ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); result.throwIfError(); for (Module module : chunk) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); List<KtFile> jetFiles = CompileEnvironmentUtil.getKtFiles( environment.getProject(), getAbsolutePaths(directory, module), new Function1<String, Unit>() { @Override public Unit invoke(String s) { throw new IllegalStateException("Should have been checked before: " + s); } }); File moduleOutputDirectory = new File(module.getOutputDirectory()); GenerationState generationState = generate( environment, result, jetFiles, module, moduleOutputDirectory, module.getModuleName()); outputFiles.put(module, generationState.getFactory()); } for (Module module : chunk) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); writeOutput( configuration, outputFiles.get(module), new File(module.getOutputDirectory()), jarPath, jarRuntime, null); } return true; }