Ignore:
Timestamp:
Aug 31, 2015, 7:05:30 PM (10 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Introduce ModuleProgramExecutable families and compile Module code to bytecode
https://bugs.webkit.org/show_bug.cgi?id=148581

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch introduces ModuleProgramExecutable, that is new executable type for the ES6 modules.
And related code block types, UninkedModuleProgramCodeBlock and ModuleProgramCodeBlock are also
introduced. BytecodeGenerator now recognizes these types and emits the bytecode and constructs
the symbol table for the module environment. While this patch introduces the bytecode generation
for the ES6 modules, the module environment instantiation initialization and imported binding
resolution are not included in this patch. They will be implemented in the subsequent patch.

The interesting part is the symbol table construction for the module environment.
Since the module code will be only executed once, the module environment need not to be allocated
and instantiated inside the module code; In the case of the function code, the function code need
to allocate the environment inside the prologue of it because the function code can be executed
more than once and the function environments are different in each time of the executions.
The module environment will be instantiated outside the module code before executing the module code.
This is required because we need to link the module environments to import the bindings before
executing the any module code in the dependency graph. And this is because the function inside the
module may be executed before the module top-level body is executed. (See the code comment for more
detailed situations)

The module environment will hold the top-most heap allocated variables in the module code.
This has the following benefits.
1) This enables JSC to perform the usual LocalClosureVar operations onto it.
2) It also makes the exported lexical variables just the heap allocated lexical variables.
3) Make it possible to initialize the heap allocated function declarations before executing the module

code. It is required under the circular dependency (see the code comment for more details).

To do so, the module environment will be constructed with the symbol table that is generated by the
bytecode generator. And the symbol table is held by the unlinked code block. That means, once the module
environment is instantiated, we cannot clear the unlinked code block before executing the module since
the layout of the instantiated module environment is coupled with the unlinked code block. This is OK
because the module code can be cleared once we executed the module code. If we failed to execute the
module (some errors occur), we can throw away the both, the module environment and the unlinked code block.

The unlinked module program code block holds the symbol table, but it does not hold the module environment.
So the unlinked module program code block can be cached. While unlinked code block can be cached, the linked
code block cannot be cached because it is already linked to the specific set of the module environment to
resolve the imported bindings.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::inferredName):
(JSC::ModuleProgramCodeBlock::replacement):
(JSC::ProgramCodeBlock::capabilityLevelInternal):
(JSC::ModuleProgramCodeBlock::capabilityLevelInternal):

  • bytecode/CodeBlock.h:

(JSC::ModuleProgramCodeBlock::ModuleProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):

  • bytecode/CodeType.cpp:

(WTF::printInternal):

  • bytecode/CodeType.h:
  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedModuleProgramCodeBlock::visitChildren):
(JSC::UnlinkedModuleProgramCodeBlock::destroy):
(JSC::UnlinkedCodeBlock::visitChildren): Deleted.

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::finishCreation): Deleted.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::instantiateLexicalVariables):
(JSC::BytecodeGenerator::emitPrefillStackTDZVariables):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::emitProgramNodeBytecode):
(JSC::ProgramNode::emitBytecode):
(JSC::ModuleProgramNode::emitBytecode):
(JSC::ImportDeclarationNode::emitBytecode):
(JSC::ExportAllDeclarationNode::emitBytecode):
(JSC::ExportDefaultDeclarationNode::emitBytecode):
(JSC::ExportLocalDeclarationNode::emitBytecode):
(JSC::ExportNamedDeclarationNode::emitBytecode):

  • interpreter/Interpreter.cpp:

(JSC::StackFrame::friendlySourceURL):
(JSC::StackFrame::friendlyFunctionName):
(JSC::getStackFrameCodeType):

  • interpreter/Interpreter.h:
  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::Frame::codeType):
(JSC::StackVisitor::Frame::functionName):
(JSC::StackVisitor::Frame::sourceURL):

  • interpreter/StackVisitor.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LLIntEntrypoint.cpp:

(JSC::LLInt::setModuleProgramEntrypoint):
(JSC::LLInt::setEntrypoint):

  • llint/LLIntOffsetsExtractor.cpp:
  • llint/LLIntThunks.cpp:

(JSC::LLInt::moduleProgramEntryThunkGenerator):

  • llint/LLIntThunks.h:
  • llint/LowLevelInterpreter.asm:
  • parser/ModuleAnalyzer.cpp:

(JSC::ModuleAnalyzer::exportVariable):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseImportClauseItem):
(JSC::Parser<LexerType>::parseExportDeclaration):

  • parser/Parser.h:

(JSC::Scope::declareLexicalVariable):

  • parser/VariableEnvironment.h:

(JSC::VariableEnvironmentEntry::isImportedNamespace):
(JSC::VariableEnvironmentEntry::setIsImportedNamespace):
(JSC::VariableEnvironment::find):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getModuleProgramCodeBlock):

  • runtime/CodeCache.h:
  • runtime/Executable.cpp:

(JSC::ScriptExecutable::installCode):
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::newReplacementCodeBlockFor):
(JSC::ModuleProgramExecutable::ModuleProgramExecutable):
(JSC::ModuleProgramExecutable::create):
(JSC::ModuleProgramExecutable::destroy):
(JSC::ModuleProgramExecutable::visitChildren):
(JSC::ModuleProgramExecutable::clearCode):
(JSC::ExecutableBase::dump):

  • runtime/Executable.h:

(JSC::ExecutableBase::isModuleProgramExecutable):
(JSC::ExecutableBase::clearCodeVirtual):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::createModuleProgramCodeBlock):

  • runtime/JSGlobalObject.h:
  • runtime/JSModuleRecord.cpp:

(JSC::JSModuleRecord::visitChildren):
(JSC::JSModuleRecord::link):

  • runtime/JSModuleRecord.h:

(JSC::JSModuleRecord::moduleProgramExecutable):

  • runtime/JSType.h:
  • runtime/ModuleLoaderObject.cpp:

(JSC::moduleLoaderObjectModuleDeclarationInstantiation):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WebCore:

Add the ModuleProgramExecutable case.

  • testing/Internals.cpp:

(WebCore::Internals::parserMetaData):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/VariableEnvironment.h

    r188434 r189201  
    4141    ALWAYS_INLINE bool isExported() const { return m_bits & IsExported; }
    4242    ALWAYS_INLINE bool isImported() const { return m_bits & IsImported; }
     43    ALWAYS_INLINE bool isImportedNamespace() const { return m_bits & IsImportedNamespace; }
    4344
    4445    ALWAYS_INLINE void setIsCaptured() { m_bits |= IsCaptured; }
     
    4849    ALWAYS_INLINE void setIsExported() { m_bits |= IsExported; }
    4950    ALWAYS_INLINE void setIsImported() { m_bits |= IsImported; }
     51    ALWAYS_INLINE void setIsImportedNamespace() { m_bits |= IsImportedNamespace; }
    5052
    5153    ALWAYS_INLINE void clearIsVar() { m_bits &= ~IsVar; }
     
    5860        IsLet = 1 << 3,
    5961        IsExported = 1 << 4,
    60         IsImported = 1 << 5
     62        IsImported = 1 << 5,
     63        IsImportedNamespace = 1 << 6
    6164    };
    6265    uint8_t m_bits { 0 };
     
    8083    ALWAYS_INLINE bool contains(const RefPtr<UniquedStringImpl>& identifier) const { return m_map.contains(identifier); }
    8184    ALWAYS_INLINE bool remove(const RefPtr<UniquedStringImpl>& identifier) { return m_map.remove(identifier); }
     85    ALWAYS_INLINE Map::iterator find(const RefPtr<UniquedStringImpl>& identifier) { return m_map.find(identifier); }
     86    ALWAYS_INLINE Map::const_iterator find(const RefPtr<UniquedStringImpl>& identifier) const { return m_map.find(identifier); }
    8287    void swap(VariableEnvironment& other);
    8388    void markVariableAsCapturedIfDefined(const RefPtr<UniquedStringImpl>& identifier);
Note: See TracChangeset for help on using the changeset viewer.