WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-148581-20150828154952.patch (text/plain), 76.15 KB, created by
Yusuke Suzuki
on 2015-08-28 15:50:05 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2015-08-28 15:50:05 PDT
Size:
76.15 KB
patch
obsolete
>Subversion Revision: 189126 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index a7cd170ddcdb36e46a7248aeae79000f0aaba822..56a81b0bdb3770b13788c5265e36d0568c428efa 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,143 @@ >+2015-08-28 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [ES6] Introduce ModuleProgramExecutable families and compile Module code to bytecode >+ https://bugs.webkit.org/show_bug.cgi?id=148581 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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): >+ * bytecompiler/BytecodeGenerator.h: >+ * bytecompiler/NodesCodegen.cpp: >+ (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: >+ > 2015-08-28 Filip Pizlo <fpizlo@apple.com> > > LICM should be sound even if the CFG has changed >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 20613bc66d1a7be1075e4a4cf40151a797227e5d..bcea88d8ef9944cb518d33ec8a3beef4f7fde7b2 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,5 +1,17 @@ > 2015-08-28 Yusuke Suzuki <utatane.tea@gmail.com> > >+ [ES6] Introduce ModuleProgramExecutable families and compile Module code to bytecode >+ https://bugs.webkit.org/show_bug.cgi?id=148581 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add the ModuleProgramExecutable case. >+ >+ * testing/Internals.cpp: >+ (WebCore::Internals::parserMetaData): >+ >+2015-08-28 Yusuke Suzuki <utatane.tea@gmail.com> >+ > Move std::function from JSFunction into NativeStdFunctionCell to correctly destroy the heap allocated std::function > https://bugs.webkit.org/show_bug.cgi?id=148262 > >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index a3c4aec3d31e43207f26a5c84de43758daa8b51f..6f3ad1bda54a5d90cd14be902777d4176d811951 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1700,6 +1700,7 @@ > E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; }; > E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* VM.cpp */; }; >+ E30677981B8BC6F5003F87F0 /* ModuleLoaderObject.js in Resources */ = {isa = PBXBuildFile; fileRef = E30677971B8BC6F5003F87F0 /* ModuleLoaderObject.js */; }; > E33637A51B63220200EE0840 /* ReflectObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E33637A31B63220200EE0840 /* ReflectObject.cpp */; }; > E33637A61B63220200EE0840 /* ReflectObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E33637A41B63220200EE0840 /* ReflectObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E33B3E261B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33B3E251B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h */; }; >@@ -3557,6 +3558,7 @@ > E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; }; > E18E3A560DF9278C00D90B34 /* VM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VM.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; > E18E3A570DF9278C00D90B34 /* VM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = VM.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; >+ E30677971B8BC6F5003F87F0 /* ModuleLoaderObject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = ModuleLoaderObject.js; sourceTree = "<group>"; }; > E33637A31B63220200EE0840 /* ReflectObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReflectObject.cpp; sourceTree = "<group>"; }; > E33637A41B63220200EE0840 /* ReflectObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReflectObject.h; sourceTree = "<group>"; }; > E33B3E251B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentationObject.lut.h; sourceTree = "<group>"; }; >@@ -5799,6 +5801,7 @@ > E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */, > E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */, > 7CF9BC5B1B65D9A3009DB1EF /* Iterator.prototype.js */, >+ E30677971B8BC6F5003F87F0 /* ModuleLoaderObject.js */, > 7CF9BC5C1B65D9B1009DB1EF /* ObjectConstructor.js */, > 7CF9BC5D1B65D9B1009DB1EF /* Operations.Promise.js */, > 7CFBAC1C18B535E500D00750 /* Promise.prototype.js */, >@@ -7045,6 +7048,7 @@ > isa = PBXResourcesBuildPhase; > buildActionMask = 2147483647; > files = ( >+ E30677981B8BC6F5003F87F0 /* ModuleLoaderObject.js in Resources */, > A53F1AC018C90F8F0072EB6D /* framework.sb in Resources */, > ); > runOnlyForDeploymentPostprocessing = 0; >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.json b/Source/JavaScriptCore/bytecode/BytecodeList.json >index 4e5a96c38ed86277442ca2619c5c8cac29ce82aa..020ec2489efe3a332985b70910deccf78d49a964 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeList.json >+++ b/Source/JavaScriptCore/bytecode/BytecodeList.json >@@ -157,6 +157,7 @@ > "bytecodes" : [ > { "name" : "llint_program_prologue" }, > { "name" : "llint_eval_prologue" }, >+ { "name" : "llint_module_program_prologue" }, > { "name" : "llint_function_for_call_prologue" }, > { "name" : "llint_function_for_construct_prologue" }, > { "name" : "llint_function_for_call_arity_check" }, >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index f8a0f4bfc8694fead28a6ab57c7c235ff13d118f..c4c66d3b7976f9775bd134d1ea989c14a45daad7 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -87,6 +87,8 @@ CString CodeBlock::inferredName() const > return "<eval>"; > case FunctionCode: > return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8(); >+ case ModuleCode: >+ return "<module>"; > default: > CRASH(); > return CString("", 0); >@@ -3062,6 +3064,11 @@ CodeBlock* ProgramCodeBlock::replacement() > return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock(); > } > >+CodeBlock* ModuleProgramCodeBlock::replacement() >+{ >+ return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock(); >+} >+ > CodeBlock* EvalCodeBlock::replacement() > { > return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock(); >@@ -3077,6 +3084,11 @@ DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal() > return DFG::programCapabilityLevel(this); > } > >+DFG::CapabilityLevel ModuleProgramCodeBlock::capabilityLevelInternal() >+{ >+ return DFG::programCapabilityLevel(this); >+} >+ > DFG::CapabilityLevel EvalCodeBlock::capabilityLevelInternal() > { > return DFG::evalCapabilityLevel(this); >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h >index cb9ebd61b5ddfe0cb3f67f310df88177dd63549b..bddd0367f3be372769adffbcfa5984318b23c788 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h >@@ -1102,10 +1102,29 @@ class ProgramCodeBlock : public GlobalCodeBlock { > #endif > }; > >+class ModuleProgramCodeBlock : public GlobalCodeBlock { >+public: >+ ModuleProgramCodeBlock(CopyParsedBlockTag, ModuleProgramCodeBlock& other) >+ : GlobalCodeBlock(CopyParsedBlock, other) >+ { >+ } >+ >+ ModuleProgramCodeBlock(ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset) >+ : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset) >+ { >+ } >+ >+#if ENABLE(JIT) >+protected: >+ virtual CodeBlock* replacement() override; >+ virtual DFG::CapabilityLevel capabilityLevelInternal() override; >+#endif >+}; >+ > class EvalCodeBlock : public GlobalCodeBlock { > public: > EvalCodeBlock(CopyParsedBlockTag, EvalCodeBlock& other) >- : GlobalCodeBlock(CopyParsedBlock, other) >+ : GlobalCodeBlock(CopyParsedBlock, other) > { > } > >@@ -1130,7 +1149,7 @@ class EvalCodeBlock : public GlobalCodeBlock { > class FunctionCodeBlock : public CodeBlock { > public: > FunctionCodeBlock(CopyParsedBlockTag, FunctionCodeBlock& other) >- : CodeBlock(CopyParsedBlock, other) >+ : CodeBlock(CopyParsedBlock, other) > { > } > >diff --git a/Source/JavaScriptCore/bytecode/CodeType.cpp b/Source/JavaScriptCore/bytecode/CodeType.cpp >index 8b2cad56ab68af12b32bf29cd840ac0aa7183d48..0c7043dfa3eaffe9f946add91793fe6257aae428 100644 >--- a/Source/JavaScriptCore/bytecode/CodeType.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeType.cpp >@@ -42,6 +42,9 @@ void printInternal(PrintStream& out, JSC::CodeType codeType) > case JSC::FunctionCode: > out.print("Function"); > return; >+ case JSC::ModuleCode: >+ out.print("Module"); >+ return; > default: > CRASH(); > return; >diff --git a/Source/JavaScriptCore/bytecode/CodeType.h b/Source/JavaScriptCore/bytecode/CodeType.h >index b8e107dcf6b670cd8283ebfa5351f7c6342f023c..9941d514cdd0c5ffe30f1a884f3ba54c6f00f893 100644 >--- a/Source/JavaScriptCore/bytecode/CodeType.h >+++ b/Source/JavaScriptCore/bytecode/CodeType.h >@@ -28,7 +28,7 @@ > > namespace JSC { > >-enum CodeType { GlobalCode, EvalCode, FunctionCode }; >+enum CodeType { GlobalCode, EvalCode, FunctionCode, ModuleCode }; > > } // namespace JSC > >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >index 574b1e4823898b38014d51829eab7f71309dbb0a..46095d84bcca60675fefde7f4002752dd9aeb50c 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >@@ -47,6 +47,7 @@ namespace JSC { > const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) }; > const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) }; > const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) }; >+const ClassInfo UnlinkedModuleProgramCodeBlock::s_info = { "UnlinkedModuleProgramCodeBlock", &Base::s_info, nullptr, CREATE_METHOD_TABLE(UnlinkedModuleProgramCodeBlock) }; > const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) }; > const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) }; > >@@ -89,7 +90,6 @@ void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) > UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); > ASSERT_GC_OBJECT_INHERITS(thisObject, info()); > Base::visitChildren(thisObject, visitor); >- visitor.append(&thisObject->m_symbolTable); > for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr) > visitor.append(ptr); > for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr) >@@ -292,6 +292,14 @@ void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) > Base::visitChildren(thisObject, visitor); > } > >+void UnlinkedModuleProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) >+{ >+ UnlinkedModuleProgramCodeBlock* thisObject = jsCast<UnlinkedModuleProgramCodeBlock*>(cell); >+ ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >+ Base::visitChildren(thisObject, visitor); >+ visitor.append(&thisObject->m_symbolTable); >+} >+ > UnlinkedCodeBlock::~UnlinkedCodeBlock() > { > } >@@ -301,6 +309,11 @@ void UnlinkedProgramCodeBlock::destroy(JSCell* cell) > jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock(); > } > >+void UnlinkedModuleProgramCodeBlock::destroy(JSCell* cell) >+{ >+ jsCast<UnlinkedModuleProgramCodeBlock*>(cell)->~UnlinkedModuleProgramCodeBlock(); >+} >+ > void UnlinkedEvalCodeBlock::destroy(JSCell* cell) > { > jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock(); >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >index 322d26199f797c10381dd45893bd5353ff1b6b46..82ce8b3563c2eae6f8ed48bd544a0be212f17f87 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >@@ -360,9 +360,6 @@ class UnlinkedCodeBlock : public JSCell { > void finishCreation(VM& vm) > { > Base::finishCreation(vm); >- if (codeType() == GlobalCode) >- return; >- m_symbolTable.set(vm, this, SymbolTable::create(vm)); > } > > private: >@@ -412,8 +409,6 @@ class UnlinkedCodeBlock : public JSCell { > FunctionExpressionVector m_functionDecls; > FunctionExpressionVector m_functionExprs; > >- WriteBarrier<SymbolTable> m_symbolTable; >- > Vector<unsigned> m_propertyAccessInstructions; > > #if ENABLE(BYTECODE_COMMENTS) >@@ -514,6 +509,71 @@ class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock { > DECLARE_INFO; > }; > >+class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock { >+private: >+ friend class CodeCache; >+ static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo& info) >+ { >+ UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedModuleProgramCodeBlock>(vm->heap)) UnlinkedModuleProgramCodeBlock(vm, vm->unlinkedModuleProgramCodeBlockStructure.get(), info); >+ instance->finishCreation(*vm); >+ return instance; >+ } >+ >+public: >+ typedef UnlinkedGlobalCodeBlock Base; >+ static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; >+ >+ static void destroy(JSCell*); >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+ >+ // This symbol table represents the layout of the module environment. This symbol table will be modified by the byte >+ // code generator since the module environment includes the top-most lexical captured variables inside the module code. >+ // This means that, once the module environment is allocated and instantiated from this symbol table, it is titely >+ // coupled with the specific unlinked module program code block and the symbol table. So before executing the module >+ // code, we should not clear the unlinked module program code block in the module executable. This requirement is met >+ // because the garbage collector only clears unlinked code in (1) unmarked executables and (2) function executables. >+ // >+ // Since the function code may be executed repeatedly and the environment of each function execution is different, >+ // the function code need to allocate and instantiate the environment in the prologue of the function code. On the >+ // other hand, the module code is executed only once. So we can instantiate the module environment outside the module >+ // code. At that time, we construct the module environment by using this symbol table before executing the module code. >+ // Instantiating the module environment before executing the module code is required to link the imported bindings >+ // between the modules. >+ // >+ // The unlinked module program code block only holds the symbol table. Not holds the module environment. So while >+ // the module environment requires the specific unlinked module program code block, the unlinked module code block >+ // can be used for the module environment instantiated from this unlinked code block. There is 1:N relation between >+ // the unlinked module code block and the module environments. So the unlinked module program code block can be cached. >+ // >+ // On the other hand, the linked code block for the module environment includes the resolved references to the imported >+ // bindings. The imported binding references the other module environment, so the linked code block is titly coupled >+ // with the specific set of the module environments. Thus, the linked code block should not be cached. >+ SymbolTable* symbolTable() { return m_symbolTable.get(); } >+ >+private: >+ UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) >+ : Base(vm, structure, ModuleCode, info) >+ { >+ } >+ >+ void finishCreation(VM& vm) >+ { >+ Base::finishCreation(vm); >+ m_symbolTable.set(vm, this, SymbolTable::create(vm)); >+ } >+ >+ WriteBarrier<SymbolTable> m_symbolTable; >+ >+public: >+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) >+ { >+ return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedModuleProgramCodeBlockType, StructureFlags), info()); >+ } >+ >+ DECLARE_INFO; >+}; >+ > class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock { > private: > friend class CodeCache; >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 62c2d3ba4257638e840bb3a62d2774b0f3127dfc..ce96edd2849d68eb782987d5952806efdc61e64c 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -70,7 +70,9 @@ ParserError BytecodeGenerator::generate() > if (m_needToInitializeArguments) > initializeVariable(variable(propertyNames().arguments), m_argumentsRegister); > >- pushLexicalScope(m_scopeNode, true); >+ // For ModuleCode, we already instantiated the environment for the lexical variables. >+ if (m_codeType != ModuleCode) >+ pushLexicalScope(m_scopeNode, true); > > { > RefPtr<RegisterID> temp = newTemporary(); >@@ -504,6 +506,181 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod > m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false)); > } > >+BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables) >+ : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) >+ , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) >+ , m_scopeNode(moduleProgramNode) >+ , m_codeBlock(vm, codeBlock) >+ , m_thisRegister(CallFrame::thisArgumentOffset()) >+ , m_codeType(ModuleCode) >+ , m_vm(&vm) >+ , m_usesNonStrictEval(false) >+{ >+ ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size()); >+ >+ for (auto& constantRegister : m_linkTimeConstantRegisters) >+ constantRegister = nullptr; >+ >+ if (m_isBuiltinFunction) >+ m_shouldEmitDebugHooks = false; >+ >+ // Use the symbol table allocated in the unlinked code block. This symbol table >+ // will be used to allocate and instantiate the module environment. >+ SymbolTable* symbolTable = codeBlock->symbolTable(); >+ symbolTable->setUsesNonStrictEval(m_usesNonStrictEval); >+ symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope); >+ >+ bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || m_codeBlock->needsFullScopeChain(); >+ bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval(); >+ if (shouldCaptureAllOfTheThings) >+ moduleProgramNode->varDeclarations().markAllVariablesAsCaptured(); >+ >+ auto captures = [&] (UniquedStringImpl* uid) -> bool { >+ if (!shouldCaptureSomeOfTheThings) >+ return false; >+ return moduleProgramNode->captures(uid); >+ }; >+ auto lookUpVarKind = [&] (UniquedStringImpl* uid, const VariableEnvironmentEntry& entry) -> VarKind { >+ // Allocate the exported variables in the module environment. >+ if (entry.isExported()) >+ return VarKind::Scope; >+ >+ // Allocate the namespace variables in the module environment to instantiate >+ // it from the outside of the module code. >+ if (entry.isImportedNamespace()) >+ return VarKind::Scope; >+ >+ if (entry.isCaptured()) >+ return VarKind::Scope; >+ return captures(uid) ? VarKind::Scope : VarKind::Stack; >+ }; >+ >+ emitOpcode(op_enter); >+ >+ allocateAndEmitScope(); >+ >+ m_calleeRegister.setIndex(JSStack::Callee); >+ >+ m_codeBlock->setNumParameters(1); // Allocate space for "this" >+ >+ for (FunctionMetadataNode* function : moduleProgramNode->functionStack()) { >+ const auto& iterator = moduleProgramNode->varDeclarations().find(function->ident().impl()); >+ RELEASE_ASSERT(iterator != moduleProgramNode->varDeclarations().end()); >+ RELEASE_ASSERT(!iterator->value.isImported()); >+ >+ VarKind varKind = lookUpVarKind(iterator->key.get(), iterator->value); >+ if (varKind == VarKind::Scope) { >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ // Section 15.2.1.16.4, step 16-a-iv-1. >+ // All heap allocated function declarations should be instantiated when the module environment >+ // is created. They include the exported function declarations and not-exported-but-heap-allocated >+ // function declarations. This is because exported function should be instantiated before executing >+ // the any module inside the dependency graph. All exported functions are instantiated before executing >+ // the actual module code execution. This enables the modules link the exported functions. >+ // >+ // Module A (executed 1st): >+ // import { b } from "B"; >+ // // Here, the module "B" is not executed yet, but the function declaration is already instantiated. >+ // // So we can call the function exported from "B". >+ // b(); >+ // >+ // export function a() { >+ // } >+ // >+ // Module B (executed 2nd): >+ // import { a } from "A"; >+ // >+ // export function b() { >+ // c(); >+ // } >+ // >+ // // c is not exported, but since it is referenced from the b, we should instantiate it before >+ // // executing the "B" module code. >+ // function c() { >+ // a(); >+ // } >+ // >+ // Module EntryPoint (executed last): >+ // import "B"; >+ // import "A"; >+ // >+ m_codeBlock->addFunctionDecl(makeFunction(function)); >+ } else { >+ // Stack allocated functions can be allocated when executing the module's body. >+ m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable)); >+ } >+ } >+ >+ // Now declare all variables. >+ >+ for (auto& entry : moduleProgramNode->varDeclarations()) { >+ ASSERT(!entry.value.isLet() && !entry.value.isConst()); >+ if (!entry.value.isVar()) // This is either a parameter or callee. >+ continue; >+ // Imported bindings are not allocated in the module environment as usual variables' way. >+ // These references remain the "Dynamic" in the unlinked code block. Later, when linking >+ // the code block, we resolve the reference to the "ModuleVar". >+ if (entry.value.isImported() && !entry.value.isImportedNamespace()) >+ continue; >+ createVariable(Identifier::fromUid(m_vm, entry.key.get()), lookUpVarKind(entry.key.get(), entry.value), symbolTable, IgnoreExisting); >+ } >+ >+ VariableEnvironment& lexicalVariables = moduleProgramNode->lexicalVariables(); >+ >+ { >+ ConcurrentJITLocker locker(symbolTable->m_lock); >+ for (auto& entry : lexicalVariables) { >+ ASSERT(entry.value.isLet() || entry.value.isConst()); >+ ASSERT(!entry.value.isVar()); >+ SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get()); >+ ASSERT(symbolTableEntry.isNull()); >+ >+ // Imported bindings are not allocated in the module environment as usual variables' way. >+ if (entry.value.isImported() && !entry.value.isImportedNamespace()) >+ continue; >+ >+ VarKind varKind = lookUpVarKind(entry.key.get(), entry.value); >+ VarOffset varOffset; >+ if (varKind == VarKind::Scope) >+ varOffset = VarOffset(symbolTable->takeNextScopeOffset(locker)); >+ else { >+ ASSERT(varKind == VarKind::Stack); >+ RegisterID* local = newBlockScopeVariable(); >+ local->ref(); >+ varOffset = VarOffset(local->virtualRegister()); >+ } >+ >+ SymbolTableEntry newEntry(varOffset, entry.value.isConst() ? ReadOnly : 0); >+ symbolTable->add(locker, entry.key.get(), newEntry); >+ } >+ } >+ >+ RegisterID* constantSymbolTable = nullptr; >+ if (vm.typeProfiler()) >+ constantSymbolTable = addConstantValue(symbolTable); >+ else >+ constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(*m_vm)); >+ >+ m_TDZStack.append(std::make_pair(lexicalVariables, true)); >+ m_symbolTableStack.append(SymbolTableStackEntry { Strong<SymbolTable>(*m_vm, symbolTable), m_scopeRegister, false, constantSymbolTable->index() }); >+ >+ // Prefill stack variables with the TDZ empty value. >+ // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated. >+ for (auto& entry : lexicalVariables) { >+ // Imported bindings are not allocated in the module environment as usual variables' way. >+ if (entry.value.isImported() && !entry.value.isImportedNamespace()) >+ continue; >+ >+ SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get()); >+ ASSERT(!symbolTableEntry.isNull()); >+ VarOffset offset = symbolTableEntry.varOffset(); >+ if (offset.isScope()) >+ continue; >+ ASSERT(offset.isStack()); >+ emitMoveEmptyValue(®isterFor(offset.stackOffset())); >+ } >+} >+ > BytecodeGenerator::~BytecodeGenerator() > { > } >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index 89cdead1354481c746670e35f96005937fb95ba7..16bbc0ddc0adf4091d8a139444abb39340f5081f 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -269,6 +269,7 @@ namespace JSC { > BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*); > BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*); > BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*); >+ BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*); > > ~BytecodeGenerator(); > >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index 9c6e76f2f42bddce965b824228ab65218fe0e17e..d4b3504f9206a5235078361553966f000c51987c 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -2895,8 +2895,17 @@ void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) > > // ------------------------------ ModuleProgramNode -------------------- > >-void ModuleProgramNode::emitBytecode(BytecodeGenerator&, RegisterID*) >+void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) > { >+ generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset()); >+ >+ RefPtr<RegisterID> dstRegister = generator.newTemporary(); >+ generator.emitLoad(dstRegister.get(), jsUndefined()); >+ generator.emitProfileControlFlow(startStartOffset()); >+ emitStatementsBytecode(generator, dstRegister.get()); >+ >+ generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset()); >+ generator.emitEnd(dstRegister.get()); > } > > // ------------------------------ EvalNode ----------------------------- >@@ -3057,30 +3066,37 @@ RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID > > void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*) > { >+ // Do nothing at runtime. > } > > // ------------------------------ ExportAllDeclarationNode -------------------- > > void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*) > { >+ // Do nothing at runtime. > } > > // ------------------------------ ExportDefaultDeclarationNode ---------------- > >-void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*) >+void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) > { >+ ASSERT(m_declaration); >+ generator.emitNode(dst, m_declaration); > } > > // ------------------------------ ExportLocalDeclarationNode ------------------ > >-void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*) >+void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) > { >+ ASSERT(m_declaration); >+ generator.emitNode(dst, m_declaration); > } > > // ------------------------------ ExportNamedDeclarationNode ------------------ > > void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*) > { >+ // Do nothing at runtime. > } > > // ------------------------------ DestructuringAssignmentNode ----------------- >diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp >index 66fa8ecf54063586cd4aaa8fb8497bc6151eb037..fa62ea6f376d88ceff4e9827543266e0d93a449c 100644 >--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp >+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp >@@ -97,6 +97,7 @@ String StackFrame::friendlySourceURL() const > > switch (codeType) { > case StackFrameEvalCode: >+ case StackFrameModuleCode: > case StackFrameFunctionCode: > case StackFrameGlobalCode: > if (!sourceURL.isEmpty()) >@@ -118,6 +119,9 @@ String StackFrame::friendlyFunctionName(CallFrame* callFrame) const > case StackFrameEvalCode: > traceLine = "eval code"; > break; >+ case StackFrameModuleCode: >+ traceLine = "module code"; >+ break; > case StackFrameNativeCode: > if (callee) > traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); >@@ -451,6 +455,8 @@ static StackFrameCodeType getStackFrameCodeType(StackVisitor& visitor) > switch (visitor->codeType()) { > case StackVisitor::Frame::Eval: > return StackFrameEvalCode; >+ case StackVisitor::Frame::Module: >+ return StackFrameModuleCode; > case StackVisitor::Frame::Function: > return StackFrameFunctionCode; > case StackVisitor::Frame::Global: >diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h >index 132c95d17f4e109ba37bbcb01872732b2f95116f..038bca5cfc75b9b245762d6e64f68f2e78ec6251 100644 >--- a/Source/JavaScriptCore/interpreter/Interpreter.h >+++ b/Source/JavaScriptCore/interpreter/Interpreter.h >@@ -54,8 +54,10 @@ namespace JSC { > class JSArrowFunction; > class JSFunction; > class JSGlobalObject; >+ class JSModuleRecord; > class LLIntOffsetsExtractor; > class ProgramExecutable; >+ class ModuleProgramExecutable; > class Register; > class JSScope; > class SamplingTool; >@@ -76,6 +78,7 @@ namespace JSC { > enum StackFrameCodeType { > StackFrameGlobalCode, > StackFrameEvalCode, >+ StackFrameModuleCode, > StackFrameFunctionCode, > StackFrameNativeCode > }; >diff --git a/Source/JavaScriptCore/interpreter/StackVisitor.cpp b/Source/JavaScriptCore/interpreter/StackVisitor.cpp >index 3f2b9140451d48834a9f71033464a2147d1bdb70..75f17723b14a47586d9ecd6636edfa469817b032 100644 >--- a/Source/JavaScriptCore/interpreter/StackVisitor.cpp >+++ b/Source/JavaScriptCore/interpreter/StackVisitor.cpp >@@ -181,6 +181,8 @@ StackVisitor::Frame::CodeType StackVisitor::Frame::codeType() const > switch (codeBlock()->codeType()) { > case EvalCode: > return CodeType::Eval; >+ case ModuleCode: >+ return CodeType::Module; > case FunctionCode: > return CodeType::Function; > case GlobalCode: >@@ -199,6 +201,9 @@ String StackVisitor::Frame::functionName() > case CodeType::Eval: > traceLine = ASCIILiteral("eval code"); > break; >+ case CodeType::Module: >+ traceLine = ASCIILiteral("module code"); >+ break; > case CodeType::Native: > if (callee) > traceLine = getCalculatedDisplayName(callFrame(), callee).impl(); >@@ -219,6 +224,7 @@ String StackVisitor::Frame::sourceURL() > > switch (codeType()) { > case CodeType::Eval: >+ case CodeType::Module: > case CodeType::Function: > case CodeType::Global: { > String sourceURL = codeBlock()->ownerScriptExecutable()->sourceURL(); >diff --git a/Source/JavaScriptCore/interpreter/StackVisitor.h b/Source/JavaScriptCore/interpreter/StackVisitor.h >index 0036a789c58e19ae13b0d4abfb75583e9bb46734..41bfc708820eccfcac735b39b4224713ebe52d69 100644 >--- a/Source/JavaScriptCore/interpreter/StackVisitor.h >+++ b/Source/JavaScriptCore/interpreter/StackVisitor.h >@@ -52,6 +52,7 @@ class StackVisitor { > Global, > Eval, > Function, >+ Module, > Native > }; > >diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp >index bbc8523f5bb23a3930c094ed486217464d86c551..84f36d540f3cbaa1aecc553adf8c4614b7bde873 100644 >--- a/Source/JavaScriptCore/jit/JIT.cpp >+++ b/Source/JavaScriptCore/jit/JIT.cpp >@@ -486,6 +486,7 @@ CompilationResult JIT::privateCompile(JITCompilationEffort effort) > > switch (m_codeBlock->codeType()) { > case GlobalCode: >+ case ModuleCode: > case EvalCode: > m_codeBlock->m_shouldAlwaysBeInlined = false; > break; >diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp >index 7313fce24200cc916169e814a0a05930aabaa53d..777cfde093a2d13df5fe5c366c9822f4ae084fae 100644 >--- a/Source/JavaScriptCore/llint/LLIntData.cpp >+++ b/Source/JavaScriptCore/llint/LLIntData.cpp >@@ -132,8 +132,8 @@ void Data::performAssertions(VM& vm) > ASSERT(maxFrameExtentForSlowPathCall == 64); > #endif > ASSERT(StringType == 6); >- ASSERT(ObjectType == 19); >- ASSERT(FinalObjectType == 20); >+ ASSERT(ObjectType == 21); >+ ASSERT(FinalObjectType == 22); > ASSERT(MasqueradesAsUndefined == 1); > ASSERT(ImplementsHasInstance == 2); > ASSERT(ImplementsDefaultHasInstance == 8); >@@ -141,6 +141,7 @@ void Data::performAssertions(VM& vm) > ASSERT(GlobalCode == 0); > ASSERT(EvalCode == 1); > ASSERT(FunctionCode == 2); >+ ASSERT(ModuleCode == 3); > > static_assert(GlobalProperty == 0, "LLInt assumes GlobalProperty ResultType is == 0"); > static_assert(GlobalVar == 1, "LLInt assumes GlobalVar ResultType is == 1"); >diff --git a/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp b/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp >index 9d00106b9a8276f48420f6b546c32d5930a36b68..a6c3d27e280a0447922869d782cfe2a55ab780c3 100644 >--- a/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp >+++ b/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp >@@ -97,12 +97,30 @@ static void setProgramEntrypoint(VM& vm, CodeBlock* codeBlock) > adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), MacroAssemblerCodePtr(), JITCode::InterpreterThunk))); > } > >+static void setModuleProgramEntrypoint(VM& vm, CodeBlock* codeBlock) >+{ >+#if ENABLE(JIT) >+ if (vm.canUseJIT()) { >+ codeBlock->setJITCode( >+ adoptRef(new DirectJITCode(vm.getCTIStub(moduleProgramEntryThunkGenerator), MacroAssemblerCodePtr(), JITCode::InterpreterThunk))); >+ return; >+ } >+#endif // ENABLE(JIT) >+ >+ UNUSED_PARAM(vm); >+ codeBlock->setJITCode( >+ adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_module_program_prologue), MacroAssemblerCodePtr(), JITCode::InterpreterThunk))); >+} >+ > void setEntrypoint(VM& vm, CodeBlock* codeBlock) > { > switch (codeBlock->codeType()) { > case GlobalCode: > setProgramEntrypoint(vm, codeBlock); > return; >+ case ModuleCode: >+ setModuleProgramEntrypoint(vm, codeBlock); >+ return; > case EvalCode: > setEvalEntrypoint(vm, codeBlock); > return; >diff --git a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp >index a2a6b2b11c5681e0b6e970c4fd11c96e19db93da..9e3f4487b085201372b2d7b27b78ce591abd970c 100644 >--- a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp >+++ b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp >@@ -42,6 +42,7 @@ > #include "VM.h" > #include "JSEnvironmentRecord.h" > #include "JSGlobalObject.h" >+#include "JSModuleRecord.h" > #include "JSObject.h" > #include "JSStack.h" > #include "JSString.h" >diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp >index 8ab96b30475fd554def8b32662496632eaf96d9a..af6884e5ede7bebe04f37b3f00091ee16f951170 100644 >--- a/Source/JavaScriptCore/llint/LLIntThunks.cpp >+++ b/Source/JavaScriptCore/llint/LLIntThunks.cpp >@@ -88,6 +88,11 @@ MacroAssemblerCodeRef programEntryThunkGenerator(VM* vm) > return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_program_prologue), "program"); > } > >+MacroAssemblerCodeRef moduleProgramEntryThunkGenerator(VM* vm) >+{ >+ return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_module_program_prologue), "module_program"); >+} >+ > } // namespace LLInt > > #else // ENABLE(JIT) >diff --git a/Source/JavaScriptCore/llint/LLIntThunks.h b/Source/JavaScriptCore/llint/LLIntThunks.h >index 0d1be6bdaeadf79487ce90668264685188a8bd12..95b0f44848bcc529d1503e289b93efe3705c8316 100644 >--- a/Source/JavaScriptCore/llint/LLIntThunks.h >+++ b/Source/JavaScriptCore/llint/LLIntThunks.h >@@ -46,6 +46,7 @@ MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(VM*); > MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(VM*); > MacroAssemblerCodeRef evalEntryThunkGenerator(VM*); > MacroAssemblerCodeRef programEntryThunkGenerator(VM*); >+MacroAssemblerCodeRef moduleProgramEntryThunkGenerator(VM*); > > } } // namespace JSC::LLInt > >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >index 136c91661f22d2d8093c198c9c5bd664438f5496..75c91f8686e4a5e085013bb119225edc97a445e4 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >@@ -161,8 +161,8 @@ const SlowPutArrayStorageShape = 30 > > # Type constants. > const StringType = 6 >-const ObjectType = 19 >-const FinalObjectType = 20 >+const ObjectType = 21 >+const FinalObjectType = 22 > > # Type flags constants. > const MasqueradesAsUndefined = 1 >@@ -176,6 +176,7 @@ const FirstConstantRegisterIndex = 0x40000000 > const GlobalCode = 0 > const EvalCode = 1 > const FunctionCode = 2 >+const ModuleCode = 3 > > # The interpreter steals the tag word of the argument count. > const LLIntReturnPC = ArgumentCount + TagOffset >@@ -884,6 +885,11 @@ _llint_program_prologue: > dispatch(0) > > >+_llint_module_program_prologue: >+ prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) >+ dispatch(0) >+ >+ > _llint_eval_prologue: > prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) > dispatch(0) >diff --git a/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp b/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >index 2fa81aacfc1f8f2bd7642f3839b3b1260587f2f2..f6238fb96802be537e91adc26b82d890b954032d 100644 >--- a/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >+++ b/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >@@ -83,7 +83,7 @@ void ModuleAnalyzer::exportVariable(const RefPtr<UniquedStringImpl>& localName, > } > > const auto& importEntry = moduleRecord()->lookUpImportEntry(localName); >- if (importEntry.isNamespace(vm())) { >+ if (variable.isImportedNamespace()) { > // Exported namespace binding. > // import * as namespace from "mod" > // export { namespace } >diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp >index 8a936157b3f6960b63ba81eb4776886fa034598a..7f0501c65312db4d4ff85dc4db13af2631ddec62 100644 >--- a/Source/JavaScriptCore/parser/Parser.cpp >+++ b/Source/JavaScriptCore/parser/Parser.cpp >@@ -2319,7 +2319,7 @@ template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerT > } > > semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name"); >- DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, DeclarationImportType::Imported); >+ DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported); > if (declarationResult != DeclarationResult::Valid) { > failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode"); > if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) >@@ -2560,10 +2560,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclara > // does not have effect on the current module's scope. But, > // export { A, B, C as D } > // will reference the current module's bindings. >- for (const Identifier* localName : maybeLocalNames) { >- currentScope()->useVariable(localName, m_vm->propertyNames->eval == *localName); >+ for (const Identifier* localName : maybeLocalNames) > currentScope()->moduleScopeData().exportBinding(*localName); >- } > } > > return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName); >diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h >index c2e6a6504089915dc28057ffe01f04eeade01f14..f697be336bb80c525042856b8c087553733a1214 100644 >--- a/Source/JavaScriptCore/parser/Parser.h >+++ b/Source/JavaScriptCore/parser/Parser.h >@@ -100,6 +100,7 @@ enum class DeclarationType { > > enum class DeclarationImportType { > Imported, >+ ImportedNamespace, > NotImported > }; > >@@ -335,6 +336,10 @@ struct Scope { > > if (importType == DeclarationImportType::Imported) > addResult.iterator->value.setIsImported(); >+ else if (importType == DeclarationImportType::ImportedNamespace) { >+ addResult.iterator->value.setIsImported(); >+ addResult.iterator->value.setIsImportedNamespace(); >+ } > > if (!addResult.isNewEntry) > result |= DeclarationResult::InvalidDuplicateDeclaration; >diff --git a/Source/JavaScriptCore/parser/VariableEnvironment.h b/Source/JavaScriptCore/parser/VariableEnvironment.h >index 5ed2a6bda92838e296482f66c0785a3611ae615c..76c7096e9e6447ebbbdb0d965a3ea4a24a5173da 100644 >--- a/Source/JavaScriptCore/parser/VariableEnvironment.h >+++ b/Source/JavaScriptCore/parser/VariableEnvironment.h >@@ -40,6 +40,7 @@ struct VariableEnvironmentEntry { > ALWAYS_INLINE bool isLet() const { return m_bits & IsLet; } > ALWAYS_INLINE bool isExported() const { return m_bits & IsExported; } > ALWAYS_INLINE bool isImported() const { return m_bits & IsImported; } >+ ALWAYS_INLINE bool isImportedNamespace() const { return m_bits & IsImportedNamespace; } > > ALWAYS_INLINE void setIsCaptured() { m_bits |= IsCaptured; } > ALWAYS_INLINE void setIsConst() { m_bits |= IsConst; } >@@ -47,6 +48,7 @@ struct VariableEnvironmentEntry { > ALWAYS_INLINE void setIsLet() { m_bits |= IsLet; } > ALWAYS_INLINE void setIsExported() { m_bits |= IsExported; } > ALWAYS_INLINE void setIsImported() { m_bits |= IsImported; } >+ ALWAYS_INLINE void setIsImportedNamespace() { m_bits |= IsImportedNamespace; } > > ALWAYS_INLINE void clearIsVar() { m_bits &= ~IsVar; } > >@@ -57,7 +59,8 @@ struct VariableEnvironmentEntry { > IsVar = 1 << 2, > IsLet = 1 << 3, > IsExported = 1 << 4, >- IsImported = 1 << 5 >+ IsImported = 1 << 5, >+ IsImportedNamespace = 1 << 6 > }; > uint8_t m_bits { 0 }; > }; >@@ -79,6 +82,8 @@ class VariableEnvironment { > ALWAYS_INLINE unsigned size() const { return m_map.size(); } > ALWAYS_INLINE bool contains(const RefPtr<UniquedStringImpl>& identifier) const { return m_map.contains(identifier); } > ALWAYS_INLINE bool remove(const RefPtr<UniquedStringImpl>& identifier) { return m_map.remove(identifier); } >+ ALWAYS_INLINE Map::iterator find(const RefPtr<UniquedStringImpl>& identifier) { return m_map.find(identifier); } >+ ALWAYS_INLINE Map::const_iterator find(const RefPtr<UniquedStringImpl>& identifier) const { return m_map.find(identifier); } > void swap(VariableEnvironment& other); > void markVariableAsCapturedIfDefined(const RefPtr<UniquedStringImpl>& identifier); > void markVariableAsCaptured(const RefPtr<UniquedStringImpl>& identifier); >diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp >index ab70eabb9e3a2a0450c629e705666f4dcca01e28..f13b25e4c9b262c525e0f56ec0f69cdc7cbedf0e 100644 >--- a/Source/JavaScriptCore/runtime/CodeCache.cpp >+++ b/Source/JavaScriptCore/runtime/CodeCache.cpp >@@ -67,11 +67,19 @@ template <typename T> struct CacheTypes { }; > template <> struct CacheTypes<UnlinkedProgramCodeBlock> { > typedef JSC::ProgramNode RootNode; > static const SourceCodeKey::CodeType codeType = SourceCodeKey::ProgramType; >+ static const SourceParseMode parseMode = SourceParseMode::ProgramMode; > }; > > template <> struct CacheTypes<UnlinkedEvalCodeBlock> { > typedef JSC::EvalNode RootNode; > static const SourceCodeKey::CodeType codeType = SourceCodeKey::EvalType; >+ static const SourceParseMode parseMode = SourceParseMode::ProgramMode; >+}; >+ >+template <> struct CacheTypes<UnlinkedModuleProgramCodeBlock> { >+ typedef JSC::ModuleProgramNode RootNode; >+ static const SourceCodeKey::CodeType codeType = SourceCodeKey::ModuleType; >+ static const SourceParseMode parseMode = SourceParseMode::ModuleEvaluateMode; > }; > > template <class UnlinkedCodeBlockType, class ExecutableType> >@@ -95,7 +103,7 @@ UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* exe > typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode; > std::unique_ptr<RootNode> rootNode = parse<RootNode>( > &vm, source, Identifier(), builtinMode, strictMode, >- SourceParseMode::ProgramMode, error, nullptr, ConstructorKind::None, thisTDZMode); >+ CacheTypes<UnlinkedCodeBlockType>::parseMode, error, nullptr, ConstructorKind::None, thisTDZMode); > if (!rootNode) > return nullptr; > >@@ -132,6 +140,12 @@ UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* execu > return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, builtinMode, strictMode, thisTDZMode, debuggerMode, profilerMode, error, variablesUnderTDZ); > } > >+UnlinkedModuleProgramCodeBlock* CodeCache::getModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) >+{ >+ VariableEnvironment emptyParentTDZVariables; >+ return getGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, builtinMode, JSParserStrictMode::Strict, ThisTDZMode::CheckIfNeeded, debuggerMode, profilerMode, error, &emptyParentTDZVariables); >+} >+ > // FIXME: There's no need to add the function's name to the key here. It's already in the source code. > UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error) > { >diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h >index af7dac7e487041319c63fec9755e239318834cb6..7175fe39512c9366e61639813cb6c4f822598de0 100644 >--- a/Source/JavaScriptCore/runtime/CodeCache.h >+++ b/Source/JavaScriptCore/runtime/CodeCache.h >@@ -45,8 +45,10 @@ class Identifier; > class JSScope; > class ParserError; > class ProgramExecutable; >+class ModuleProgramExecutable; > class UnlinkedCodeBlock; > class UnlinkedEvalCodeBlock; >+class UnlinkedModuleProgramCodeBlock; > class UnlinkedFunctionCodeBlock; > class UnlinkedFunctionExecutable; > class UnlinkedProgramCodeBlock; >@@ -56,7 +58,7 @@ class SourceProvider; > > class SourceCodeKey { > public: >- enum CodeType { EvalType, ProgramType, FunctionType }; >+ enum CodeType { EvalType, ProgramType, FunctionType, ModuleType }; > > SourceCodeKey() > { >@@ -257,6 +259,7 @@ class CodeCache { > > UnlinkedProgramCodeBlock* getProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ProfilerMode, ParserError&); > UnlinkedEvalCodeBlock* getEvalCodeBlock(VM&, EvalExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, ThisTDZMode, DebuggerMode, ProfilerMode, ParserError&, const VariableEnvironment*); >+ UnlinkedModuleProgramCodeBlock* getModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, JSParserBuiltinMode, DebuggerMode, ProfilerMode, ParserError&); > UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(VM&, const Identifier&, const SourceCode&, ParserError&); > > void clear() >diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp >index e4854797567de8cdbe96615702fb6e751b63c5fd..b1d0055ecf0243429faf19edaff8fe06539b6d75 100644 >--- a/Source/JavaScriptCore/runtime/Executable.cpp >+++ b/Source/JavaScriptCore/runtime/Executable.cpp >@@ -161,7 +161,18 @@ void ScriptExecutable::installCode(CodeBlock* genericCodeBlock) > executable->m_programCodeBlock = codeBlock; > break; > } >- >+ >+ case ModuleCode: { >+ ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this); >+ ModuleProgramCodeBlock* codeBlock = static_cast<ModuleProgramCodeBlock*>(genericCodeBlock); >+ >+ ASSERT(kind == CodeForCall); >+ >+ oldCodeBlock = executable->m_moduleProgramCodeBlock; >+ executable->m_moduleProgramCodeBlock = codeBlock; >+ break; >+ } >+ > case EvalCode: { > EvalExecutable* executable = jsCast<EvalExecutable*>(this); > EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock); >@@ -228,7 +239,17 @@ RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor( > executable, executable->m_unlinkedProgramCodeBlock.get(), scope, > executable->source().provider(), executable->source().startColumn())); > } >- >+ >+ if (classInfo() == ModuleProgramExecutable::info()) { >+ ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this); >+ RELEASE_ASSERT(kind == CodeForCall); >+ RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock); >+ RELEASE_ASSERT(!function); >+ return adoptRef(new ModuleProgramCodeBlock( >+ executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope, >+ executable->source().provider(), executable->source().startColumn())); >+ } >+ > RELEASE_ASSERT(classInfo() == FunctionExecutable::info()); > RELEASE_ASSERT(function); > FunctionExecutable* executable = jsCast<FunctionExecutable*>(this); >@@ -285,6 +306,17 @@ PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor( > return result; > } > >+ if (classInfo() == ModuleProgramExecutable::info()) { >+ RELEASE_ASSERT(kind == CodeForCall); >+ ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this); >+ ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>( >+ executable->m_moduleProgramCodeBlock->baselineVersion()); >+ RefPtr<ModuleProgramCodeBlock> result = adoptRef(new ModuleProgramCodeBlock( >+ CodeBlock::CopyParsedBlock, *baseline)); >+ result->setAlternative(baseline); >+ return result; >+ } >+ > RELEASE_ASSERT(classInfo() == FunctionExecutable::info()); > FunctionExecutable* executable = jsCast<FunctionExecutable*>(this); > FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>( >@@ -385,6 +417,36 @@ void ProgramExecutable::destroy(JSCell* cell) > static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable(); > } > >+const ClassInfo ModuleProgramExecutable::s_info = { "ModuleProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ModuleProgramExecutable) }; >+ >+ModuleProgramExecutable::ModuleProgramExecutable(ExecState* exec, const SourceCode& source) >+ : ScriptExecutable(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false) >+{ >+ m_typeProfilingStartOffset = 0; >+ m_typeProfilingEndOffset = source.length() - 1; >+ if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler()) >+ exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset); >+} >+ >+ModuleProgramExecutable* ModuleProgramExecutable::create(ExecState* exec, const SourceCode& source) >+{ >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); >+ ModuleProgramExecutable* executable = new (NotNull, allocateCell<ModuleProgramExecutable>(*exec->heap())) ModuleProgramExecutable(exec, source); >+ executable->finishCreation(exec->vm()); >+ >+ UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCode = globalObject->createModuleProgramCodeBlock(exec, executable); >+ if (!unlinkedModuleProgramCode) >+ return nullptr; >+ executable->m_unlinkedModuleProgramCodeBlock.set(exec->vm(), executable, unlinkedModuleProgramCode); >+ >+ return executable; >+} >+ >+void ModuleProgramExecutable::destroy(JSCell* cell) >+{ >+ static_cast<ModuleProgramExecutable*>(cell)->ModuleProgramExecutable::~ModuleProgramExecutable(); >+} >+ > const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) }; > > FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, >@@ -517,6 +579,23 @@ void ProgramExecutable::clearCode() > Base::clearCode(); > } > >+void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) >+{ >+ ModuleProgramExecutable* thisObject = jsCast<ModuleProgramExecutable*>(cell); >+ ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >+ ScriptExecutable::visitChildren(thisObject, visitor); >+ visitor.append(&thisObject->m_unlinkedModuleProgramCodeBlock); >+ if (thisObject->m_moduleProgramCodeBlock) >+ thisObject->m_moduleProgramCodeBlock->visitAggregate(visitor); >+} >+ >+void ModuleProgramExecutable::clearCode() >+{ >+ m_moduleProgramCodeBlock = nullptr; >+ m_unlinkedModuleProgramCodeBlock.clear(); >+ Base::clearCode(); >+} >+ > FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind) > { > FunctionCodeBlock* result; >@@ -647,6 +726,15 @@ void ExecutableBase::dump(PrintStream& out) const > out.print("ProgramExecutable w/o CodeBlock"); > return; > } >+ >+ if (classInfo() == ModuleProgramExecutable::info()) { >+ ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(realThis); >+ if (CodeBlock* codeBlock = executable->codeBlock()) >+ out.print(*codeBlock); >+ else >+ out.print("ModuleProgramExecutable w/o CodeBlock"); >+ return; >+ } > > FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis); > if (!function->eitherCodeBlock()) >diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h >index a9c41c4521603d70233dc202c973ddd65e0d9a37..cdceb304265f976d0077aefd657b5b7babbf2a16 100644 >--- a/Source/JavaScriptCore/runtime/Executable.h >+++ b/Source/JavaScriptCore/runtime/Executable.h >@@ -54,8 +54,10 @@ class JSScope; > class JSWASMModule; > class LLIntOffsetsExtractor; > class ProgramCodeBlock; >+class ModuleProgramCodeBlock; >+class JSScope; > class WebAssemblyCodeBlock; >- >+ > enum CompilationKind { FirstCompilation, OptimizingCompilation }; > > inline bool isCall(CodeSpecializationKind kind) >@@ -106,6 +108,11 @@ class ExecutableBase : public JSCell { > { > return type() == ProgramExecutableType; > } >+ bool isModuleProgramExecutable() >+ { >+ return type() == ModuleProgramExecutableType; >+ } >+ > > bool isHostFunction() const > { >@@ -550,6 +557,49 @@ class ProgramExecutable final : public ScriptExecutable { > RefPtr<ProgramCodeBlock> m_programCodeBlock; > }; > >+class ModuleProgramExecutable final : public ScriptExecutable { >+ friend class LLIntOffsetsExtractor; >+public: >+ typedef ScriptExecutable Base; >+ static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; >+ >+ static ModuleProgramExecutable* create(ExecState*, const SourceCode&); >+ >+ static void destroy(JSCell*); >+ >+ ModuleProgramCodeBlock* codeBlock() >+ { >+ return m_moduleProgramCodeBlock.get(); >+ } >+ >+ PassRefPtr<JITCode> generatedJITCode() >+ { >+ return generatedJITCodeForCall(); >+ } >+ >+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) >+ { >+ return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info()); >+ } >+ >+ DECLARE_INFO; >+ >+ void clearCode(); >+ >+ ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); } >+ UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } >+ >+private: >+ friend class ScriptExecutable; >+ >+ ModuleProgramExecutable(ExecState*, const SourceCode&); >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+ >+ WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; >+ RefPtr<ModuleProgramCodeBlock> m_moduleProgramCodeBlock; >+}; >+ > class FunctionExecutable final : public ScriptExecutable { > friend class JIT; > friend class LLIntOffsetsExtractor; >@@ -742,6 +792,8 @@ inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) > case WebAssemblyExecutableType: > return jsCast<WebAssemblyExecutable*>(executable)->clearCode(); > #endif >+ case ModuleProgramExecutableType: >+ return jsCast<ModuleProgramExecutable*>(executable)->clearCode(); > default: > return jsCast<NativeExecutable*>(executable)->clearCode(); > } >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index 98663dfcb082c7aab07a695b9093c7dc459d1c22..432d07b97d8c169f73dce273fb4e8eb9d83db620 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -933,6 +933,25 @@ UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, > return unlinkedCodeBlock; > } > >+UnlinkedModuleProgramCodeBlock* JSGlobalObject::createModuleProgramCodeBlock(CallFrame* callFrame, ModuleProgramExecutable* executable) >+{ >+ ParserError error; >+ DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff; >+ ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff; >+ UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getModuleProgramCodeBlock( >+ vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, debuggerMode, profilerMode, error); >+ >+ if (hasDebugger()) >+ debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message()); >+ >+ if (error.isValid()) { >+ throwVMError(callFrame, error.toErrorObject(this, executable->source())); >+ return nullptr; >+ } >+ >+ return unlinkedCodeBlock; >+} >+ > void JSGlobalObject::setRemoteDebuggingEnabled(bool enabled) > { > #if ENABLE(REMOTE_INSPECTOR) >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h >index 1a5250c67cd146efbcfd1127c570638aa413b196..1ca31b7b126fb2efd3b7190eaf764f5cda0991fe 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h >@@ -78,6 +78,7 @@ class JSStack; > class LLIntOffsetsExtractor; > class Microtask; > class ModuleLoaderObject; >+class ModuleProgramExecutable; > class NativeErrorConstructor; > class ObjectConstructor; > class ProgramCodeBlock; >@@ -85,6 +86,7 @@ class ProgramExecutable; > class RegExpConstructor; > class RegExpPrototype; > class SourceCode; >+class UnlinkedModuleProgramCodeBlock; > class NullGetterFunction; > class NullSetterFunction; > enum class ThisTDZMode; >@@ -643,6 +645,7 @@ class JSGlobalObject : public JSSegmentedVariableObject { > > UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception); > UnlinkedEvalCodeBlock* createEvalCodeBlock(CallFrame*, EvalExecutable*, ThisTDZMode, const VariableEnvironment*); >+ UnlinkedModuleProgramCodeBlock* createModuleProgramCodeBlock(CallFrame*, ModuleProgramExecutable*); > > protected: > struct GlobalPropertyInfo { >diff --git a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >index 5d15ebc36c8420ef6ecd54ee053d9a3315f6ab8b..7b606374a6060b77020c4ef4512e9245e03f3fc5 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >+++ b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >@@ -26,6 +26,8 @@ > #include "config.h" > #include "JSModuleRecord.h" > >+#include "Error.h" >+#include "Executable.h" > #include "IdentifierInlines.h" > #include "JSCJSValueInlines.h" > #include "JSCellInlines.h" >@@ -58,6 +60,7 @@ void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor) > { > JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell); > Base::visitChildren(thisObject, visitor); >+ visitor.append(&thisObject->m_moduleProgramExecutable); > visitor.append(&thisObject->m_dependenciesMap); > } > >@@ -90,8 +93,14 @@ JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const > return jsCast<JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value"))); > } > >-void JSModuleRecord::link(ExecState*) >+void JSModuleRecord::link(ExecState* exec) > { >+ ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode()); >+ if (!executable) { >+ throwSyntaxError(exec); >+ return; >+ } >+ m_moduleProgramExecutable.set(exec->vm(), this, executable); > } > > JSValue JSModuleRecord::execute(ExecState*) >diff --git a/Source/JavaScriptCore/runtime/JSModuleRecord.h b/Source/JavaScriptCore/runtime/JSModuleRecord.h >index 936263ccf3129da95e31e91a21940dd0a9552645..81da3966e8c5a8da9304d282f4fbca94f24eae48 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleRecord.h >+++ b/Source/JavaScriptCore/runtime/JSModuleRecord.h >@@ -117,6 +117,8 @@ class JSModuleRecord : public JSDestructibleObject { > void link(ExecState*); > JSValue execute(ExecState*); > >+ ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); } >+ > private: > JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) > : Base(vm, structure) >@@ -154,6 +156,7 @@ class JSModuleRecord : public JSDestructibleObject { > // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation > OrderedIdentifierSet m_requestedModules; > >+ WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable; > WriteBarrier<JSMap> m_dependenciesMap; > }; > >diff --git a/Source/JavaScriptCore/runtime/JSType.h b/Source/JavaScriptCore/runtime/JSType.h >index 1596e6584c8aeb8b7c0ccb4da303020098e695ff..110f8b5ac9db71d33167d859b2d469f3e7a5fa52 100644 >--- a/Source/JavaScriptCore/runtime/JSType.h >+++ b/Source/JavaScriptCore/runtime/JSType.h >@@ -41,11 +41,13 @@ enum JSType : uint8_t { > > EvalExecutableType, > ProgramExecutableType, >+ ModuleProgramExecutableType, > FunctionExecutableType, > WebAssemblyExecutableType, > > UnlinkedFunctionExecutableType, > UnlinkedProgramCodeBlockType, >+ UnlinkedModuleProgramCodeBlockType, > UnlinkedEvalCodeBlockType, > UnlinkedFunctionCodeBlockType, > >diff --git a/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp b/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >index e67fa385bff771c4e3d8a2d79117b13a57238ea1..28e0badaa72af30cc771919604a612d6cdb73e07 100644 >--- a/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >+++ b/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >@@ -274,6 +274,9 @@ EncodedJSValue JSC_HOST_CALL moduleLoaderObjectModuleDeclarationInstantiation(Ex > dataLog("Loader [link] ", moduleRecord->moduleKey(), "\n"); > > moduleRecord->link(exec); >+ if (exec->hadException()) >+ return JSValue::encode(jsUndefined()); >+ > return JSValue::encode(jsUndefined()); > } > >diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp >index 962dc52ddd67ec699e10ac692da05941271f32c3..827bb368ad81e35f547ca1b177734cab583d33b3 100644 >--- a/Source/JavaScriptCore/runtime/VM.cpp >+++ b/Source/JavaScriptCore/runtime/VM.cpp >@@ -225,6 +225,7 @@ VM::VM(VMType vmType, HeapType heapType) > #if ENABLE(WEBASSEMBLY) > webAssemblyExecutableStructure.set(*this, WebAssemblyExecutable::createStructure(*this, 0, jsNull())); > #endif >+ moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull())); > regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); > symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull())); > symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull())); >@@ -236,6 +237,7 @@ VM::VM(VMType vmType, HeapType heapType) > unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); > unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); > unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); >+ unlinkedModuleProgramCodeBlockStructure.set(*this, UnlinkedModuleProgramCodeBlock::createStructure(*this, 0, jsNull())); > propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); > weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull())); > inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull())); >diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h >index c4e80379e8c23922bfb683831fec13b4c3a687aa..84a535ab7d1ddb4cbd66b3dd5988ae629f7f9a0b 100644 >--- a/Source/JavaScriptCore/runtime/VM.h >+++ b/Source/JavaScriptCore/runtime/VM.h >@@ -103,6 +103,7 @@ class UnlinkedCodeBlock; > class UnlinkedEvalCodeBlock; > class UnlinkedFunctionExecutable; > class UnlinkedProgramCodeBlock; >+class UnlinkedModuleProgramCodeBlock; > class VirtualRegister; > class VMEntryScope; > class Watchdog; >@@ -282,6 +283,7 @@ class VM : public ThreadSafeRefCounted<VM> { > #if ENABLE(WEBASSEMBLY) > Strong<Structure> webAssemblyExecutableStructure; > #endif >+ Strong<Structure> moduleProgramExecutableStructure; > Strong<Structure> regExpStructure; > Strong<Structure> symbolStructure; > Strong<Structure> symbolTableStructure; >@@ -293,6 +295,7 @@ class VM : public ThreadSafeRefCounted<VM> { > Strong<Structure> unlinkedProgramCodeBlockStructure; > Strong<Structure> unlinkedEvalCodeBlockStructure; > Strong<Structure> unlinkedFunctionCodeBlockStructure; >+ Strong<Structure> unlinkedModuleProgramCodeBlockStructure; > Strong<Structure> propertyTableStructure; > Strong<Structure> weakMapDataStructure; > Strong<Structure> inferredValueStructure; >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index 8f2ac0950e6a9bab193ad0e8d26309f1c4d3e610..fe95c57e3a2a725a667527bbb498b644299aac97 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -1483,6 +1483,8 @@ String Internals::parserMetaData(Deprecated::ScriptValue value) > result.appendLiteral("function \""); > result.append(inferredName); > result.append('"'); >+ } else if (executable->isModuleProgramExecutable()) >+ result.appendLiteral("module"); > } else if (executable->isEvalExecutable()) > result.appendLiteral("eval"); > else if (executable->isProgramExecutable())
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 148581
:
260186
|
260197
|
260198
|
260219