More fun with scopes and ScriptObjectMirror
attila.szegedi at oracle.com
Thu Dec 12 01:08:22 PST 2013
On Dec 12, 2013, at 10:02 AM, Tim Fox <timvolpe at gmail.com> wrote:
> On 12/12/13 08:49, Attila Szegedi wrote:
>> On Dec 12, 2013, at 8:00 AM, Tim Fox <timvolpe at gmail.com> wrote:
>>> On 11/12/13 12:53, Attila Szegedi wrote:
>>>> On Dec 11, 2013, at 1:13 PM, Tim Fox <timvolpe at gmail.com> wrote:
>>>>> I assumed that if two scripts where run with their own script context, then they would already have separate globals, i.e. if I do
>>>>> myglobal = 1
>>>>> in module 1 that won't be visible in module 2.
>>>> That's true, but then you also end up with the need for ScriptObjectMirrors between them, and that was what I suggested you try to avoid.
>>>>> So I'm not sure really what --global-per-engine really means, if the modules have their own globals anyway. I guess my understanding must be wrong somewhere.
>>>> Well, it will mean that modules won't have their own globals… --global-per-engine will make it so that the Global object is specific to the ScriptEngine, and not to the ScriptContext, e.g. even if you replace the ScriptContext of the engine, when scripts are run, they'll still see the same global object as before the replacement. The gist of it is:
>>>> a) without --global-per-engine, the Global object is specific to a ScriptContext, each ScriptContext has its own. ENGINE_SCOPE Bindings object of the context is actually a mirror of its Global.
>>>> b) with --global-per-engine, the Global object lives in the ScriptEngine. ENGINE_SCOPE Bindings object of the context is just a vanilla SimpleBindings (or whatever you set it to), and Global will delegate property getters for non-existent properties to it (but it'll still receive property setters, so new global variables created by one script will be visible by another; no isolation there).
>> Not much. Using separate ScriptContexts with single engine is pretty much equivalent to modifying the initial ScriptContext of the engine. When I thought you'll end up using Java code to implement module loading, I suggested either using separate contexts, or at least changing the ENGINE_SCOPE bindings of the original context to contain "module", "exports", etc. but if you now implement those as parameters of an anonymous function that you put around the module source code and eval(), then you don't need even that.
> Regarding thread safety... Unlike node, Vert.x is multi-threaded, however we guarantee that code in a particular Verticle is never executed concurrently by more than one thread.
> In other words - we have a single engine which might contain many scripts, and may have many threads executing different scripts in it at any one time, but we guarantee that any particular script is never executed concurrently by more than one thread. So we don't need any multithreaded JS semantics.
> This works well with Rhino and DynJS. So I assume it's ok for a single engine to be executed concurrently as long as those threads don't bump into each other, i.e. don't try and execute the same code concurrently?
Code execution is not a concern, multiple threads executing same code is okay. Concurrent mutation of shared data is a concern. If those verticles also have data separation, and whatever data they share they only use as read-only (talking about native JS objects, arrays, and global vars here; you can obviously share threadsafe POJOs). Native JS objects and arrays in Nashorn aren't threadsafe. That's a conscious design decision; since the language doesn't have defined multithreaded semantics, it doesn't make much sense to pay the price for it in terms of code complexity and runtime cost.
More information about the nashorn-dev