设计建议:llvm多个运行时上下文 [英] design suggestion: llvm multiple runtime contexts

查看:421
本文介绍了设计建议:llvm多个运行时上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序需要在同一个(单线程)进程中运行许多单独的上下文。它们都共享一个 LLVMContext



该进程将运行许多上下文(在线程意义上);也就是说,每个基于 boost :: context (仍然在库,预批准的lib)上的连续对象中运行一个函数,这意味着每个上下文都可以产生,但是它们基本上在同一个单线程进程中运行。每个应该运行基本上独立于其他,更重要的是,每个编译错误应该不会影响其他人的执行。



每个上下文,将动态调用跨越多个翻译单元(TU)的代码。一些翻译单元可以在许多这些上下文之间共享。新的或修改的翻译单元中的编译错误不应影响其他上下文。



澄清编辑
例如,T.U. A可以在两个上下文X和Y之间共享,只是为了获得完整的图片,假设X也将运行来自其他翻译单元(即B和D)的代码,而Y也将具有C.在一些点,X决定对A进行修改,因此它创建了一个新的TU A.1,它是A的一个副本,并在那里应用修改,所以这些不会影响上下文Y.希望这个例子清楚地表明需求。



我最初的想法是为每个上下文关联一个 llvm :: Module ,但由于它在LLVM中未定义发生在一个处于中间编译状态的模块,我决定为每个翻译单元添加一个 llvm :: Module (参见),加上我之前解释的翻译单元的修改发生在上下文的本地的写时拷贝策略,以避免修改影响其他上下文。



我遇到的主要两重问题是:





我有一个第二个问题是: / p>


  • 我需要多少 ExecutionEngine 一个用于整个应用程序?每个上下文一个?每个模块一个?



希望问题的范围不会太大。

解决方案

我认为你需要一个概念框架来悬挂你的想法。将各种执行位视为命令(甚至可能甚至使用命令模式实现)将给你一个更明显的交互点集。话虽如此;您将需要一个上下文用于您希望返回的每个离散执行。超过两个将需要你创建适当的书本。我相信两个是基本上免费处理boost。

执行位之间的通信类似于你。创建跨执行上下文共享的状态(记忆)是一个解决方案。您也可能已经在运行时内置了适当的状态,则不需要额外的图层。正如你指出,全球化不是你在这些互动中的朋友。
版本控制和名称解析也是一个问题。保持执行位分离对解决这个问题有很大的帮助。一旦您解决协调问题,这更多是跟踪您已经创建的位。这也意味着没有必要回收,只是创建新的每次,没有重新加载。一旦它们完成执行,您还必须管理这些位的寿命结束。
我正在为每个执行位建议一个 ExecutionEngine 。不这样做意味着更多的工作试图保护工作代码的代码的错误的影响。我相信有可能用单个引擎做到这一点,但这将是非常危险的。


My application needs to run many separate contexts in the same (single-threaded) process. They all share a single LLVMContext.

The process will run many contexts (in the thread sense); that is, each one runs a function in a continuation object based on boost::context (still on vault, pre-approved lib) it means that each context can yield, but they basically run in the same single-threaded process. Each one should run basically independent of the other, and more importantly, a compilation error in each one should not affect the execution of the others.

Each of these contexts, will invoke code dynamically that spans multiple translation units (TU). some Translation units may be shared across many of these contexts. compilation errors in a new or modified translation unit should not affect other contexts.

Clarification Edit: For example, T.U. A might be shared among two contexts, context X and Y. just for the sake of having a full picture, lets say that X will also be running code from other translations units, I.e B and D, while Y will have also C. At some point, X decides to make a modification to A, so it creates a new T.U A.1, which is a copy of A, and applies the modification there, so those will not affect context Y. Hope this example makes it clear the requirement.

My initial impulse was to associate one llvm::Module for each context, but since its undefined in LLVM what happens with a module in an intermediate state of compilation, I decided to add one llvm::Module for each translation unit (see this question for the reason), plus the copy-on-write policy I explained before for when modifications of a translation unit happen locally to a context, in order to avoid a modification affecting other contexts.

The main two-fold question I've have is:

  • How do I link together the different modules in a context in order to invoke them as an unified library? I'm using the C++ api. I'm particularly wary of this nasty, old bug affecting this functionality. Would this bug still affect me if I transferred ownership of all the modules to the JIT with ExecutionEngine::addModule()?

  • What are the required steps once a modification on a translation unit forces the update of one of the modules? do I need to drop/delete the old module object and create a new one? is there a recycling policy that I haven't read about?

A secondary question I have about this is:

  • How many ExecutionEngine do I need? one for the whole application? one per context? one per module?

Hope the scope of the question is not too overwhelming.

解决方案

I think you need a conceptual framework to "hang" your ideas on. Thinking of the various executing bits as commands (perhaps even implementing using the command pattern) will give you a more obvious set of interaction points. That being said; you will need a context for each discrete execution you wish to return to. More than two will require that you create appropriate book keeping. I believe that two is handled essentially for free in boost.
Communication between executing bits is similarly up to you. Creating a state (memento) that is shared across execution contexts is one solution that comes to mind. You may also already have suitable state built into your run time, then no extra layer will be required. As you pointed out globals are not your friend in these interactions. Versioning and Name resolution are also an issue. Keeping the executing bits separate goes a long way toward solving this problem. Once you resolve the coordination issue this is more a matter of tracking what bits you have already created. This also means that there is no need for recycling, just create new each time and there is no reload. You will also have to manage the end of life of these bits once they have completed executing. I am proposing one ExecutionEngine per executing bit. To not do this means a great deal more work attempting to "protect" working code from the effects of code that is wrong. I believe it is possible to do this with a single engine, but it would be significantly more risky.

这篇关于设计建议:llvm多个运行时上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆