Closed Bug 1243808 Opened 9 years ago Closed 9 years ago

Allow modules to be compiled off main thread

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla47
Tracking Status
firefox47 --- fixed

People

(Reporter: jonco, Assigned: jonco)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 1 obsolete file)

The browser can compile scripts on a helper thread and hence reduce jank for large scripts.  We want to be able to do that for modules too.
This works very like off-main-thread-compilation for scripts.  There are a couple of wrinkles:
 - there are new prototypes to fix up after merging compartments
 - the module scope chain needs fixing after merging too
 - you can't currently freeze objects if you only have an ExclusiveContext so this is deferred until we're on the main thread again
Attachment #8713288 - Flags: review?(shu)
Updated patch in light of recent static scope changes.
Attachment #8713288 - Attachment is obsolete: true
Attachment #8713288 - Flags: review?(shu)
Attachment #8716355 - Flags: review?(shu)
Comment on attachment 8716355 [details] [diff] [review]
bug1243808-off-thread-compilation v2

Review of attachment 8716355 [details] [diff] [review]:
-----------------------------------------------------------------

Looks fine to me; thanks for the refactoring. Sorry it took so long.

::: js/src/frontend/BytecodeCompiler.cpp
@@ +771,5 @@
>      CompileOptions options(cx, optionsInput);
>      options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
>      options.setIsRunOnce(true);
>  
>      Rooted<StaticScope*> staticScope(cx, &cx->global()->lexicalScope().staticBlock());

Since this function can now be called from off thread, please copy the warning about passing in the current context's global lexical scope being incorrect if we start optimizing global bindings.

@@ +781,5 @@
> +
> +    // This happens in GlobalHelperThreadState::finishModuleParseTask() when a
> +    // module is compiled off main thread.
> +    if (cx->isJSContext() && !ModuleObject::FreezeArrayProperties(cx->asJSContext(), module))
> +        return nullptr;

Hm I don't really like this duplication.

As a followup, we should take a look at splitting out a NativeObject-only version of SetIntegrityLevel that takes an ExclusiveContext*. From a quick reading, I think most of the calls in that function that takes a JSContext* have to do with proxies.

::: js/src/shell/js.cpp
@@ +3448,5 @@
>      const char16_t* chars = stableChars.twoByteRange().start().get();
>      SourceBufferHolder srcBuf(chars, scriptContents->length(),
>                                SourceBufferHolder::NoOwnership);
>  
> +    RootedObject module(cx, frontend::CompileModule(cx, options, srcBuf));

Huh. The global argument was unused?

::: js/src/vm/HelperThreads.cpp
@@ +1147,5 @@
>  
>      // Make sure we have all the constructors we need for the prototype
>      // remapping below, since we can't GC while that's happening.
>      Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
> +    if (!EnsureParserCreatedClasses(cx, kind)) {

Shouldn't this already be done from the call to |CreateGlobalForOffThreadParse| when we started the parse task?

@@ +1254,5 @@
> +
> +        // Module objects don't have standard prototypes either.
> +        JSObject* moduleProto = parseGlobal->maybeGetModulePrototype();
> +        JSObject* importEntryProto = parseGlobal->maybeGetImportEntryPrototype();
> +        JSObject* exportEntryProto = parseGlobal->maybeGetExportEntryPrototype();

Making sure I understand correctly: these calls to get the module-related protos are using the "maybe" variant because they will only be created when doing off-thread parsing of modules, not global scripts?
Attachment #8716355 - Flags: review?(shu) → review+
(In reply to Shu-yu Guo [:shu] from comment #3)

> Since this function can now be called from off thread, please copy the
> warning about passing in the current context's global lexical scope being
> incorrect if we start optimizing global bindings.

Done.

> As a followup, we should take a look at splitting out a NativeObject-only
> version of SetIntegrityLevel that takes an ExclusiveContext*. From a quick
> reading, I think most of the calls in that function that takes a JSContext*
> have to do with proxies.

Sure.  I filed bug 1247194 for this.

> Huh. The global argument was unused?

Yes, it gets everything it needs from the context.

> Shouldn't this already be done from the call to
> |CreateGlobalForOffThreadParse| when we started the parse task?

Yes I think so.  I'll change this for assertions.
 
> Making sure I understand correctly: these calls to get the module-related
> protos are using the "maybe" variant because they will only be created when
> doing off-thread parsing of modules, not global scripts?

Yes, we don't create them if we're not parsing a module.
(In reply to Jon Coppeard (:jonco) (Away until 22nd Feb?) from comment #4)

> > Shouldn't this already be done from the call to
> > |CreateGlobalForOffThreadParse| when we started the parse task?
> 
> Yes I think so.  I'll change this for assertions.

This caused the debug/bug-1238610.js jit-test to fail due to missing array prototype at this point, so I'll leave this as it was.
caused bustage and so backed out for https://treeherder.mozilla.org/logviewer.html#?job_id=21420628&repo=mozilla-inbound
Flags: needinfo?(jcoppeard)
Depends on: 1247666
Depends on: 1221144
Flags: needinfo?(jcoppeard)
https://hg.mozilla.org/mozilla-central/rev/48b7c3fa5914
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla47
Depends on: 1250842
Depends on: 1368313
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: