Title: [278588] trunk/Source/_javascript_Core
Revision
278588
Author
[email protected]
Date
2021-06-07 18:43:14 -0700 (Mon, 07 Jun 2021)

Log Message

Introduce LexicalScopeFeatures to enable future bytecode optimizations
https://bugs.webkit.org/show_bug.cgi?id=224072

Reviewed by Keith Miller.

Before this patch, BytecodeGenerator was capable of reasoning about the presence of `with`
statements, direct `eval`, or any other code features only within the current executable:

    ```
    with (foo) {
        (function() {
            // There was no way to detect WithScope during generation of this function.
        })();
    }
    ```

This change is required for op_to_this rewrite (#225397): if FunctionCallResolveNode and
friends knew there is no WithScope, op_call could be emitted with |this| value of
`undefined` as per spec [1], instead of resolved scope. This would:
  - simplify op_to_this on all tiers, likely resulting in minor perf boost;
  - save 1 instruction per strict function by removing op_to_this;
  - remove toThis() from the method table and ~30 its call sites from built-ins;
  - fix built-in methods that were observably lacking toThis();
  - fix __proto__ getter / setter called on global scope;
  - fix WebIDL accessors called with |this| value of `undefined` and `null`.

Also, if ResolveNode knew that unforgeable global properties are not shadowed and there
is no `with` statement or sloppy mode direct `eval`, then `undefined` / `Infinity` / `NaN`
lookups could be constant-folded. This would save up to 3 bytecode ops per each usage
and allow emitting op_is_undefined_or_null for `x === undefined || x === null`.
V8 performs this optimization [2].

This patch introduces LexicalScopeFeatures to allow passing such information from Parser
to BytecodeGenerator with a minimal code diff. These features are kept separate from
CodeFeature to simplify reasoning about feature's scope and because we need to propagate
lexical features from parent to child scope.

Strict mode is the first use case of LexicalScopeFeatures, which this change carefully
fits into existing abstractions without increasing their memory usage even by 1 byte.

[1]: https://tc39.es/ecma262/#sec-evaluatecall (step 2)
[2]: https://medium.com/@bmeurer/sometimes-undefined-is-defined-7701e1c9eff8

* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createExecutable):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::recordParse):
(JSC::UnlinkedCodeBlock::lexicalScopeFeatures const):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::setInvalidTypeProfilingOffsets):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitNewClassFieldInitializerFunction):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::lexicalScopeFeatures const):
(JSC::BytecodeGenerator::generate):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionMetadata):
* parser/Nodes.cpp:
(JSC::ScopeNode::ScopeNode):
(JSC::ProgramNode::ProgramNode):
(JSC::ModuleProgramNode::ModuleProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionMetadataNode::FunctionMetadataNode):
(JSC::FunctionMetadataNode::operator== const):
(JSC::FunctionMetadataNode::dump const):
(JSC::FunctionNode::FunctionNode):
* parser/Nodes.h:
(JSC::ScopeNode::lexicalScopeFeatures):
(JSC::ScopeNode::isStrictMode const):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseGeneratorFunctionSourceElements):
(JSC::Parser<LexerType>::parseAsyncFunctionSourceElements):
(JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
(JSC::Parser<LexerType>::parseFunctionBody):
(JSC::Parser<LexerType>::parseFunctionInfo):
* parser/Parser.h:
(JSC::Scope::Scope):
(JSC::Scope::lexicalScopeFeatures const):
(JSC::Scope::setStrictMode):
(JSC::Scope::strictMode const):
(JSC::Scope::fillParametersForSourceProviderCache):
(JSC::Scope::restoreFromSourceProviderCache):
(JSC::Parser::pushScope):
(JSC::Parser::lexicalScopeFeatures):
(JSC::Parser<LexerType>::parse):
* parser/ParserModes.h:
* parser/SourceProviderCacheItem.h:
(JSC::SourceProviderCacheItem::lexicalScopeFeatures const):
(JSC::SourceProviderCacheItem::SourceProviderCacheItem):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createFunctionMetadata):
* runtime/CachedBytecode.cpp:
(JSC::CachedBytecode::addFunctionUpdate):
* runtime/CachedTypes.cpp:
(JSC::CachedFunctionExecutable::lexicalScopeFeatures const):
(JSC::CachedCodeBlock::lexicalScopeFeatures const):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
(JSC::CachedFunctionExecutable::encode):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::CachedCodeBlock<CodeBlockType>::encode):
(JSC::CachedFunctionExecutable::isInStrictContext const): Deleted.
* runtime/CachedTypes.h:
* runtime/CodeCache.cpp:
(JSC::generateUnlinkedCodeBlockImpl):
(JSC::CodeCache::getUnlinkedGlobalCodeBlock):
* runtime/ECMAMode.h:
(JSC::ECMAMode::fromBool):
* runtime/FunctionExecutable.cpp:
(JSC::FunctionExecutable::FunctionExecutable):
* runtime/GlobalExecutable.h:
(JSC::GlobalExecutable::recordParse):
(JSC::GlobalExecutable::GlobalExecutable):
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::ScriptExecutable):
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::recordParse):
* runtime/ScriptExecutable.h:
(JSC::ScriptExecutable::isInStrictContext const):
(JSC::ScriptExecutable::recordParse):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (278587 => 278588)


--- trunk/Source/_javascript_Core/ChangeLog	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-06-08 01:43:14 UTC (rev 278588)
@@ -1,3 +1,132 @@
+2021-06-07  Alexey Shvayka  <[email protected]>
+
+        Introduce LexicalScopeFeatures to enable future bytecode optimizations
+        https://bugs.webkit.org/show_bug.cgi?id=224072
+
+        Reviewed by Keith Miller.
+
+        Before this patch, BytecodeGenerator was capable of reasoning about the presence of `with`
+        statements, direct `eval`, or any other code features only within the current executable:
+
+            ```
+            with (foo) {
+                (function() {
+                    // There was no way to detect WithScope during generation of this function.
+                })();
+            }
+            ```
+
+        This change is required for op_to_this rewrite (#225397): if FunctionCallResolveNode and
+        friends knew there is no WithScope, op_call could be emitted with |this| value of
+        `undefined` as per spec [1], instead of resolved scope. This would:
+          - simplify op_to_this on all tiers, likely resulting in minor perf boost;
+          - save 1 instruction per strict function by removing op_to_this;
+          - remove toThis() from the method table and ~30 its call sites from built-ins;
+          - fix built-in methods that were observably lacking toThis();
+          - fix __proto__ getter / setter called on global scope;
+          - fix WebIDL accessors called with |this| value of `undefined` and `null`.
+
+        Also, if ResolveNode knew that unforgeable global properties are not shadowed and there
+        is no `with` statement or sloppy mode direct `eval`, then `undefined` / `Infinity` / `NaN`
+        lookups could be constant-folded. This would save up to 3 bytecode ops per each usage
+        and allow emitting op_is_undefined_or_null for `x === undefined || x === null`.
+        V8 performs this optimization [2].
+
+        This patch introduces LexicalScopeFeatures to allow passing such information from Parser
+        to BytecodeGenerator with a minimal code diff. These features are kept separate from
+        CodeFeature to simplify reasoning about feature's scope and because we need to propagate
+        lexical features from parent to child scope.
+
+        Strict mode is the first use case of LexicalScopeFeatures, which this change carefully
+        fits into existing abstractions without increasing their memory usage even by 1 byte.
+
+        [1]: https://tc39.es/ecma262/#sec-evaluatecall (step 2)
+        [2]: https://medium.com/@bmeurer/sometimes-undefined-is-defined-7701e1c9eff8
+
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createExecutable):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::recordParse):
+        (JSC::UnlinkedCodeBlock::lexicalScopeFeatures const):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        (JSC::UnlinkedFunctionExecutable::setInvalidTypeProfilingOffsets):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitNewClassFieldInitializerFunction):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::lexicalScopeFeatures const):
+        (JSC::BytecodeGenerator::generate):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionMetadata):
+        * parser/Nodes.cpp:
+        (JSC::ScopeNode::ScopeNode):
+        (JSC::ProgramNode::ProgramNode):
+        (JSC::ModuleProgramNode::ModuleProgramNode):
+        (JSC::EvalNode::EvalNode):
+        (JSC::FunctionMetadataNode::FunctionMetadataNode):
+        (JSC::FunctionMetadataNode::operator== const):
+        (JSC::FunctionMetadataNode::dump const):
+        (JSC::FunctionNode::FunctionNode):
+        * parser/Nodes.h:
+        (JSC::ScopeNode::lexicalScopeFeatures):
+        (JSC::ScopeNode::isStrictMode const):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::parseGeneratorFunctionSourceElements):
+        (JSC::Parser<LexerType>::parseAsyncFunctionSourceElements):
+        (JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
+        (JSC::Parser<LexerType>::parseFunctionBody):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        * parser/Parser.h:
+        (JSC::Scope::Scope):
+        (JSC::Scope::lexicalScopeFeatures const):
+        (JSC::Scope::setStrictMode):
+        (JSC::Scope::strictMode const):
+        (JSC::Scope::fillParametersForSourceProviderCache):
+        (JSC::Scope::restoreFromSourceProviderCache):
+        (JSC::Parser::pushScope):
+        (JSC::Parser::lexicalScopeFeatures):
+        (JSC::Parser<LexerType>::parse):
+        * parser/ParserModes.h:
+        * parser/SourceProviderCacheItem.h:
+        (JSC::SourceProviderCacheItem::lexicalScopeFeatures const):
+        (JSC::SourceProviderCacheItem::SourceProviderCacheItem):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createFunctionMetadata):
+        * runtime/CachedBytecode.cpp:
+        (JSC::CachedBytecode::addFunctionUpdate):
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedFunctionExecutable::lexicalScopeFeatures const):
+        (JSC::CachedCodeBlock::lexicalScopeFeatures const):
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        (JSC::CachedFunctionExecutable::encode):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        (JSC::CachedCodeBlock<CodeBlockType>::encode):
+        (JSC::CachedFunctionExecutable::isInStrictContext const): Deleted.
+        * runtime/CachedTypes.h:
+        * runtime/CodeCache.cpp:
+        (JSC::generateUnlinkedCodeBlockImpl):
+        (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
+        * runtime/ECMAMode.h:
+        (JSC::ECMAMode::fromBool):
+        * runtime/FunctionExecutable.cpp:
+        (JSC::FunctionExecutable::FunctionExecutable):
+        * runtime/GlobalExecutable.h:
+        (JSC::GlobalExecutable::recordParse):
+        (JSC::GlobalExecutable::GlobalExecutable):
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::ScriptExecutable):
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::recordParse):
+        * runtime/ScriptExecutable.h:
+        (JSC::ScriptExecutable::isInStrictContext const):
+        (JSC::ScriptExecutable::recordParse):
+
 2021-06-07  Commit Queue  <[email protected]>
 
         Unreviewed, reverting r278371 and r278463.

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -198,7 +198,7 @@
 
     FunctionMetadataNode metadata(
         start, end, startColumn, endColumn, source.startOffset() + functionKeywordStart, source.startOffset() + functionNameStart, source.startOffset() + parametersStart,
-        isInStrictContext, constructorKind, constructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded,
+        isInStrictContext ? StrictModeLexicalFeature : NoLexicalFeatures, constructorKind, constructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded,
         parameterCount, parseMode, isArrowFunctionBodyExpression);
 
     metadata.finishParsing(newSource, Identifier(), FunctionMode::FunctionExpression);

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -42,8 +42,11 @@
 
 UnlinkedCodeBlock::UnlinkedCodeBlock(VM& vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, OptionSet<CodeGenerationMode> codeGenerationMode)
     : Base(vm, structure)
+    , m_numVars(0)
     , m_usesCallEval(false)
+    , m_numCalleeLocals(0)
     , m_isConstructor(info.isConstructor())
+    , m_numParameters(0)
     , m_hasCapturedVariables(false)
     , m_isBuiltinFunction(info.isBuiltinFunction())
     , m_superBinding(static_cast<unsigned>(info.superBinding()))

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -242,9 +242,10 @@
 
     bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned lineCount, unsigned endColumn)
+    void recordParse(CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, bool hasCapturedVariables, unsigned lineCount, unsigned endColumn)
     {
         m_features = features;
+        m_lexicalScopeFeatures = lexicalScopeFeatures;
         m_hasCapturedVariables = hasCapturedVariables;
         m_lineCount = lineCount;
         // For the UnlinkedCodeBlock, startColumn is always 0.
@@ -257,6 +258,7 @@
     void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL.impl(); }
 
     CodeFeatures codeFeatures() const { return m_features; }
+    LexicalScopeFeatures lexicalScopeFeatures() const { return static_cast<LexicalScopeFeatures>(m_lexicalScopeFeatures); }
     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
     unsigned lineCount() const { return m_lineCount; }
     ALWAYS_INLINE unsigned startColumn() const { return 0; }
@@ -368,9 +370,13 @@
     VirtualRegister m_thisRegister;
     VirtualRegister m_scopeRegister;
 
+    unsigned m_numVars : 31;
     unsigned m_usesCallEval : 1;
+    unsigned m_numCalleeLocals : 31;
     unsigned m_isConstructor : 1;
+    unsigned m_numParameters : 31;
     unsigned m_hasCapturedVariables : 1;
+
     unsigned m_isBuiltinFunction : 1;
     unsigned m_superBinding : 1;
     unsigned m_scriptMode: 1;
@@ -385,6 +391,7 @@
     unsigned m_age : 3;
     static_assert(((1U << 3) - 1) >= maxAge);
     bool m_hasCheckpoints : 1;
+    unsigned m_lexicalScopeFeatures : 4;
 public:
     ConcurrentJSLock m_lock;
 private:
@@ -395,10 +402,6 @@
     unsigned m_lineCount { 0 };
     unsigned m_endColumn { UINT_MAX };
 
-    unsigned m_numVars { 0 };
-    unsigned m_numCalleeLocals { 0 };
-    unsigned m_numParameters { 0 };
-
     PackedRefPtr<StringImpl> m_sourceURLDirective;
     PackedRefPtr<StringImpl> m_sourceMappingURLDirective;
 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -65,7 +65,7 @@
     }
 
     function->finishParsing(executable->name(), executable->functionMode());
-    executable->recordParse(function->features(), function->hasCapturedVariables());
+    executable->recordParse(function->features(), function->lexicalScopeFeatures(), function->hasCapturedVariables());
 
     bool isClassContext = executable->superBinding() == SuperBinding::Needed || executable->parseMode() == SourceParseMode::ClassFieldInitializerMode;
 
@@ -73,8 +73,7 @@
 
     auto parentScopeTDZVariables = executable->parentScopeTDZVariables();
     const PrivateNameEnvironment* parentPrivateNameEnvironment = executable->parentPrivateNameEnvironment();
-    ECMAMode ecmaMode = executable->isInStrictContext() ? ECMAMode::strict() : ECMAMode::sloppy();
-    error = BytecodeGenerator::generate(vm, function.get(), source, result, codeGenerationMode, parentScopeTDZVariables, parentPrivateNameEnvironment, ecmaMode);
+    error = BytecodeGenerator::generate(vm, function.get(), source, result, codeGenerationMode, parentScopeTDZVariables, parentPrivateNameEnvironment);
 
     if (error.isValid())
         return nullptr;
@@ -85,7 +84,7 @@
 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, std::optional<PrivateNameEnvironment> parentPrivateNameEnvironment, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor)
     : Base(vm, structure)
     , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt())
-    , m_isInStrictContext(node->isInStrictContext())
+    , m_isGeneratedFromCache(false)
     , m_lineCount(node->lastLine() - node->firstLine())
     , m_hasCapturedVariables(false)
     , m_unlinkedFunctionNameStart(node->functionNameStart() - parentSource.startOffset())
@@ -101,16 +100,16 @@
     , m_parametersStartOffset(node->parametersStart())
     , m_isCached(false)
     , m_typeProfilingStartOffset(node->functionKeywordStart())
+    , m_needsClassFieldInitializer(static_cast<unsigned>(needsClassFieldInitializer))
     , m_typeProfilingEndOffset(node->startStartOffset() + node->source().length() - 1)
     , m_parameterCount(node->parameterCount())
     , m_privateBrandRequirement(static_cast<unsigned>(privateBrandRequirement))
     , m_features(0)
+    , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
     , m_sourceParseMode(node->parseMode())
-    , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
+    , m_lexicalScopeFeatures(node->lexicalScopeFeatures())
     , m_functionMode(static_cast<unsigned>(node->functionMode()))
     , m_derivedContextType(static_cast<unsigned>(derivedContextType))
-    , m_isGeneratedFromCache(false)
-    , m_needsClassFieldInitializer(static_cast<unsigned>(needsClassFieldInitializer))
     , m_unlinkedCodeBlockForCall()
     , m_unlinkedCodeBlockForConstruct()
     , m_name(node->ident())
@@ -290,7 +289,7 @@
 
 void UnlinkedFunctionExecutable::setInvalidTypeProfilingOffsets()
 {
-    m_typeProfilingStartOffset = std::numeric_limits<unsigned>::max();
+    m_typeProfilingStartOffset = INT32_MAX;
     m_typeProfilingEndOffset = std::numeric_limits<unsigned>::max();
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -97,7 +97,7 @@
         ensureRareData().m_classSource = source;
     }
 
-    bool isInStrictContext() const { return m_isInStrictContext; }
+    bool isInStrictContext() const { return m_lexicalScopeFeatures & StrictModeLexicalFeature; }
     FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
@@ -134,13 +134,15 @@
         vm.unlinkedFunctionExecutableSpace.set.remove(this);
     }
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables)
+    void recordParse(CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, bool hasCapturedVariables)
     {
         m_features = features;
+        m_lexicalScopeFeatures = lexicalScopeFeatures;
         m_hasCapturedVariables = hasCapturedVariables;
     }
 
-    CodeFeatures features() const { return m_features; }
+    CodeFeatures features() const { return static_cast<CodeFeatures>(m_features); }
+    LexicalScopeFeatures lexicalScopeFeatures() const { return static_cast<LexicalScopeFeatures>(m_lexicalScopeFeatures); }
     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
 
     PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); }
@@ -254,7 +256,7 @@
     }
 
     unsigned m_firstLineOffset : 31;
-    unsigned m_isInStrictContext : 1;
+    unsigned m_isGeneratedFromCache : 1;
     unsigned m_lineCount : 31;
     unsigned m_hasCapturedVariables : 1;
     unsigned m_unlinkedFunctionNameStart : 31;
@@ -269,17 +271,17 @@
     unsigned m_superBinding : 1;
     unsigned m_parametersStartOffset : 31;
     unsigned m_isCached : 1;
-    unsigned m_typeProfilingStartOffset;
+    unsigned m_typeProfilingStartOffset : 31;
+    unsigned m_needsClassFieldInitializer : 1;
     unsigned m_typeProfilingEndOffset;
     unsigned m_parameterCount : 31;
     unsigned m_privateBrandRequirement : 1;
-    CodeFeatures m_features;
+    unsigned m_features : 14;
+    unsigned m_constructorKind : 2;
     SourceParseMode m_sourceParseMode;
-    unsigned m_constructorKind : 2;
+    unsigned m_lexicalScopeFeatures : 4;
     unsigned m_functionMode : 2; // FunctionMode
     unsigned m_derivedContextType: 2;
-    unsigned m_isGeneratedFromCache : 1;
-    unsigned m_needsClassFieldInitializer : 1;
 
     union {
         WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -289,7 +289,7 @@
     return ParserError(ParserError::ErrorNone);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(programNode)
@@ -302,7 +302,7 @@
     , m_usesNonStrictEval(false)
     , m_inTailPosition(false)
     , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval())
-    , m_ecmaMode(ecmaMode)
+    , m_ecmaMode(ECMAMode::fromBool(programNode->isStrictMode()))
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables);
 
@@ -336,7 +336,7 @@
     }
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(functionNode)
@@ -346,7 +346,7 @@
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
     , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
-    , m_usesNonStrictEval(functionNode->usesEval() && !ecmaMode.isStrict())
+    , m_usesNonStrictEval(functionNode->usesEval() && !functionNode->isStrictMode())
     // FIXME: We should be able to have tail call elimination with the profiler
     // enabled. This is currently not possible because the profiler expects
     // op_will_call / op_did_call pairs before and after a call, which are not
@@ -354,11 +354,12 @@
     // https://bugs.webkit.org/show_bug.cgi?id=148819
     //
     // Note that we intentionally enable tail call for naked constructors since it does not have special code for "return".
-    , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && ecmaMode.isStrict())
+    , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && functionNode->isStrictMode())
     , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
-    , m_ecmaMode(ecmaMode)
+    , m_ecmaMode(ECMAMode::fromBool(functionNode->isStrictMode()))
     , m_derivedContextType(codeBlock->derivedContextType())
 {
+    ECMAMode ecmaMode = m_ecmaMode;
     pushPrivateAccessNames(parentPrivateNameEnvironment);
 
     SymbolTable* functionSymbolTable = SymbolTable::create(m_vm);
@@ -844,7 +845,7 @@
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(evalNode)
@@ -854,10 +855,10 @@
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
     , m_isBuiltinFunction(false)
-    , m_usesNonStrictEval(evalNode->usesEval() && !ecmaMode.isStrict())
+    , m_usesNonStrictEval(evalNode->usesEval() && !evalNode->isStrictMode())
     , m_inTailPosition(false)
     , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval())
-    , m_ecmaMode(ecmaMode)
+    , m_ecmaMode(ECMAMode::fromBool(evalNode->isStrictMode()))
     , m_derivedContextType(codeBlock->derivedContextType())
 {
     m_codeBlock->setNumParameters(1);
@@ -909,7 +910,7 @@
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(moduleProgramNode)
@@ -922,7 +923,7 @@
     , m_usesNonStrictEval(false)
     , m_inTailPosition(false)
     , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval())
-    , m_ecmaMode(ecmaMode)
+    , m_ecmaMode(ECMAMode::strict())
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables);
 
@@ -3269,8 +3270,7 @@
     SourceParseMode parseMode = SourceParseMode::ClassFieldInitializerMode;
     ConstructAbility constructAbility = ConstructAbility::CannotConstruct;
 
-    const bool alwaysStrictInClass = true;
-    FunctionMetadataNode metadata(parserArena(), JSTokenLocation(), JSTokenLocation(), 0, 0, 0, 0, 0, alwaysStrictInClass, ConstructorKind::None, superBinding, 0, parseMode, false);
+    FunctionMetadataNode metadata(parserArena(), JSTokenLocation(), JSTokenLocation(), 0, 0, 0, 0, 0, StrictModeLexicalFeature, ConstructorKind::None, superBinding, 0, parseMode, false);
     metadata.finishParsing(m_scopeNode->source(), Identifier(), FunctionMode::MethodDefinition);
     auto initializer = UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), &metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(variablesUnderTDZ), WTFMove(parentPrivateNameEnvironment), newDerivedContextType, NeedsClassFieldInitializer::No, PrivateBrandRequirement::None);
     initializer->setClassFieldLocations(WTFMove(classFieldLocations));

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (278587 => 278588)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -409,10 +409,10 @@
     public:
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
-        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
-        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
-        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
+        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*);
+        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*);
+        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*);
+        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*);
 
         ~BytecodeGenerator();
         
@@ -426,6 +426,7 @@
         bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; }
         bool usesEval() const { return m_scopeNode->usesEval(); }
         bool usesThis() const { return m_scopeNode->usesThis(); }
+        LexicalScopeFeatures lexicalScopeFeatures() const { return m_scopeNode->lexicalScopeFeatures(); }
         PrivateBrandRequirement privateBrandRequirement() const { return m_codeBlock->privateBrandRequirement(); }
         ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
         SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
@@ -433,7 +434,7 @@
         NeedsClassFieldInitializer needsClassFieldInitializer() const { return m_codeBlock->needsClassFieldInitializer(); }
 
         template<typename Node, typename UnlinkedCodeBlock>
-        static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* privateNameEnvironment, ECMAMode ecmaMode)
+        static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* privateNameEnvironment)
         {
             MonotonicTime before;
             if (UNLIKELY(Options::reportBytecodeCompileTimes()))
@@ -440,7 +441,7 @@
                 before = MonotonicTime::now();
 
             DeferGC deferGC(vm.heap);
-            auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, parentScopeTDZVariables, privateNameEnvironment, ecmaMode);
+            auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, parentScopeTDZVariables, privateNameEnvironment);
             auto result = bytecodeGenerator->generate();
 
             if (UNLIKELY(Options::reportBytecodeCompileTimes())) {

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -462,7 +462,7 @@
     FunctionMetadataNode* createFunctionMetadata(
         const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, 
         unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
-        int functionNameStart, int parametersStart, bool inStrictContext, 
+        int functionNameStart, int parametersStart, LexicalScopeFeatures lexicalScopeFeatures, 
         ConstructorKind constructorKind, SuperBinding superBinding,
         unsigned parameterCount,
         SourceParseMode mode, bool isArrowFunctionBodyExpression)
@@ -470,7 +470,7 @@
         return new (m_parserArena) FunctionMetadataNode(
             m_parserArena, startLocation, endLocation, startColumn, endColumn, 
             functionKeywordStart, functionNameStart, parametersStart, 
-            inStrictContext, constructorKind, superBinding,
+            lexicalScopeFeatures, constructorKind, superBinding,
             parameterCount, mode, isArrowFunctionBodyExpression);
     }
 

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -117,13 +117,14 @@
 
 // ------------------------------ ScopeNode -----------------------------
 
-ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext)
+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, LexicalScopeFeatures lexicalScopeFeatures)
     : StatementNode(endLocation)
     , ParserArenaRoot(parserArena)
     , m_startLineNumber(startLocation.line)
     , m_startStartOffset(startLocation.startOffset)
     , m_startLineStartOffset(startLocation.lineStartOffset)
-    , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
+    , m_features(NoFeatures)
+    , m_lexicalScopeFeatures(lexicalScopeFeatures)
     , m_innerArrowFunctionCodeFeatures(NoInnerArrowFunctionFeatures)
     , m_numConstants(0)
     , m_statements(nullptr)
@@ -130,7 +131,7 @@
 {
 }
 
-ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
     : StatementNode(endLocation)
     , ParserArenaRoot(parserArena)
     , VariableEnvironmentNode(lexicalVariables, WTFMove(funcStack))
@@ -138,6 +139,7 @@
     , m_startStartOffset(startLocation.startOffset)
     , m_startLineStartOffset(startLocation.lineStartOffset)
     , m_features(features)
+    , m_lexicalScopeFeatures(lexicalScopeFeatures)
     , m_innerArrowFunctionCodeFeatures(innerArrowFunctionCodeFeatures)
     , m_source(source)
     , m_sloppyModeHoistedFunctions(WTFMove(sloppyModeHoistedFunctions))
@@ -164,8 +166,8 @@
 
 // ------------------------------ ProgramNode -----------------------------
 
-ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
+ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)
 {
@@ -173,8 +175,8 @@
 
 // ------------------------------ ModuleProgramNode -----------------------------
 
-ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
+ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&& moduleScopeData)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)
     , m_usesAwait(features & AwaitFeature)
@@ -184,8 +186,8 @@
 
 // ------------------------------ EvalNode -----------------------------
 
-EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
+EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters*, const SourceCode& source, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_endColumn(endColumn)
 {
 }
@@ -195,10 +197,10 @@
 FunctionMetadataNode::FunctionMetadataNode(
     ParserArena&, const JSTokenLocation& startLocation, 
     const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, 
-    int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, 
+    int functionKeywordStart, int functionNameStart, int parametersStart, LexicalScopeFeatures lexicalScopeFeatures,
     ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
         : Node(endLocation)
-        , m_isInStrictContext(isInStrictContext)
+        , m_lexicalScopeFeatures(lexicalScopeFeatures)
         , m_superBinding(static_cast<unsigned>(superBinding))
         , m_constructorKind(static_cast<unsigned>(constructorKind))
         , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No))
@@ -220,10 +222,10 @@
 FunctionMetadataNode::FunctionMetadataNode(
     const JSTokenLocation& startLocation, 
     const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, 
-    int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, 
+    int functionKeywordStart, int functionNameStart, int parametersStart, LexicalScopeFeatures lexicalScopeFeatures, 
     ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
         : Node(endLocation)
-        , m_isInStrictContext(isInStrictContext)
+        , m_lexicalScopeFeatures(lexicalScopeFeatures)
         , m_superBinding(static_cast<unsigned>(superBinding))
         , m_constructorKind(static_cast<unsigned>(constructorKind))
         , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No))
@@ -258,7 +260,7 @@
 bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const
 {
     return m_parseMode == other.m_parseMode
-        && m_isInStrictContext == other.m_isInStrictContext
+        && m_lexicalScopeFeatures == other.m_lexicalScopeFeatures
         && m_superBinding == other.m_superBinding
         && m_constructorKind == other.m_constructorKind
         && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression
@@ -281,7 +283,7 @@
 void FunctionMetadataNode::dump(PrintStream& stream) const
 {
     stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode));
-    stream.println("m_isInStrictContext ", m_isInStrictContext);
+    stream.println("m_lexicalScopeFeatures ", m_lexicalScopeFeatures);
     stream.println("m_superBinding ", m_superBinding);
     stream.println("m_constructorKind ", m_constructorKind);
     stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression);
@@ -304,8 +306,8 @@
 
 // ------------------------------ FunctionNode -----------------------------
 
-FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
-    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, innerArrowFunctionCodeFeatures, numConstants)
+FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)
+    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, WTFMove(sloppyModeHoistedFunctions), features, lexicalScopeFeatures, innerArrowFunctionCodeFeatures, numConstants)
     , m_parameters(parameters)
     , m_startColumn(startColumn)
     , m_endColumn(endColumn)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -1897,8 +1897,8 @@
         // new for allocation.
         using ParserArenaRoot::operator new;
 
-        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext);
-        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
+        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, LexicalScopeFeatures);
+        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
 
         const SourceCode& source() const { return m_source; }
         intptr_t sourceID() const { return m_source.providerID(); }
@@ -1908,6 +1908,7 @@
         int startLineStartOffset() const { return m_startLineStartOffset; }
 
         CodeFeatures features() { return m_features; }
+        LexicalScopeFeatures lexicalScopeFeatures() { return m_lexicalScopeFeatures; }
         InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures() { return m_innerArrowFunctionCodeFeatures; }
         bool doAnyInnerArrowFunctionsUseAnyFeature() { return m_innerArrowFunctionCodeFeatures != NoInnerArrowFunctionFeatures; }
         bool doAnyInnerArrowFunctionsUseArguments() { return m_innerArrowFunctionCodeFeatures & ArgumentsInnerArrowFunctionFeature; }
@@ -1920,7 +1921,7 @@
         bool usesEval() const { return m_features & EvalFeature; }
         bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
         bool usesArrowFunction() const { return m_features & ArrowFunctionFeature; }
-        bool isStrictMode() const { return m_features & StrictModeFeature; }
+        bool isStrictMode() const { return m_lexicalScopeFeatures & StrictModeLexicalFeature; }
         bool usesThis() const { return m_features & ThisFeature; }
         bool usesSuperCall() const { return m_features & SuperCallFeature; }
         bool usesSuperProperty() const { return m_features & SuperPropertyFeature; }
@@ -1962,6 +1963,7 @@
 
     private:
         CodeFeatures m_features;
+        LexicalScopeFeatures m_lexicalScopeFeatures;
         InnerArrowFunctionCodeFeatures m_innerArrowFunctionCodeFeatures;
         SourceCode m_source;
         VariableEnvironment m_varDeclarations;
@@ -1972,7 +1974,7 @@
 
     class ProgramNode final : public ScopeNode {
     public:
-        ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
@@ -1987,7 +1989,7 @@
 
     class EvalNode final : public ScopeNode {
     public:
-        EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         ALWAYS_INLINE unsigned startColumn() const { return 0; }
         unsigned endColumn() const { return m_endColumn; }
@@ -2002,7 +2004,7 @@
 
     class ModuleProgramNode final : public ScopeNode {
     public:
-        ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
@@ -2171,13 +2173,13 @@
         FunctionMetadataNode(
             ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, 
             unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
-            int functionNameStart, int parametersStart, bool isInStrictContext, 
+            int functionNameStart, int parametersStart, LexicalScopeFeatures, 
             ConstructorKind, SuperBinding, unsigned parameterCount,
             SourceParseMode, bool isArrowFunctionBodyExpression);
         FunctionMetadataNode(
             const JSTokenLocation& start, const JSTokenLocation& end, 
             unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
-            int functionNameStart, int parametersStart, bool isInStrictContext, 
+            int functionNameStart, int parametersStart, LexicalScopeFeatures, 
             ConstructorKind, SuperBinding, unsigned parameterCount,
             SourceParseMode, bool isArrowFunctionBodyExpression);
 
@@ -2210,7 +2212,7 @@
         void setClassSource(const SourceCode& source) { m_classSource = source; }
 
         int startStartOffset() const { return m_startStartOffset; }
-        bool isInStrictContext() const { return m_isInStrictContext; }
+        LexicalScopeFeatures lexicalScopeFeatures() const { return static_cast<LexicalScopeFeatures>(m_lexicalScopeFeatures); }
         SuperBinding superBinding() { return static_cast<SuperBinding>(m_superBinding); }
         ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); }
         bool isConstructorAndNeedsClassFieldInitializer() const { return m_needsClassFieldInitializer; }
@@ -2236,7 +2238,7 @@
         }
 
     public:
-        unsigned m_isInStrictContext : 1;
+        unsigned m_lexicalScopeFeatures : 4;
         unsigned m_superBinding : 1;
         unsigned m_constructorKind : 2;
         unsigned m_needsClassFieldInitializer : 1;
@@ -2260,7 +2262,7 @@
 
     class FunctionNode final : public ScopeNode {
     public:
-        FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
+        FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, LexicalScopeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&);
 
         FunctionParameters* parameters() const { return m_parameters; }
 

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -309,8 +309,6 @@
     }
 
     CodeFeatures features = context.features();
-    if (scope->strictMode())
-        features |= StrictModeFeature;
     if (scope->shadowsArguments())
         features |= ShadowsArgumentsFeature;
     if (m_seenTaggedTemplate)
@@ -533,7 +531,7 @@
         failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
         popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
     }
-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, lexicalScopeFeatures(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
 
     info.endLine = tokenLine();
     info.endOffset = m_token.m_data.offset;
@@ -584,7 +582,7 @@
         }
         popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
     }
-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, lexicalScopeFeatures(), ConstructorKind::None, m_superBinding, info.parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
 
     info.endLine = tokenLine();
     info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
@@ -635,7 +633,7 @@
         }
         popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
     }
-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, parseMode, isArrowFunctionBodyExpression);
+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, lexicalScopeFeatures(), ConstructorKind::None, m_superBinding, info.parameterCount, parseMode, isArrowFunctionBodyExpression);
 
     info.endLine = tokenLine();
     info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
@@ -2170,7 +2168,7 @@
         if (match(CLOSEBRACE)) {
             unsigned endColumn = tokenColumn();
             SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
-            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
+            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, lexicalScopeFeatures(), constructorKind, functionSuperBinding, parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
         }
     }
 
@@ -2189,7 +2187,7 @@
     }
     unsigned endColumn = tokenColumn();
     SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
-    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
+    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, lexicalScopeFeatures(), constructorKind, functionSuperBinding, parameterCount, sourceParseMode(), isArrowFunctionBodyExpression);
 }
 
 static const char* stringArticleForFunctionMode(SourceParseMode mode)
@@ -2405,7 +2403,7 @@
         // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
         if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(parametersStart) : nullptr) {
             // If we're in a strict context, the cached function info must say it was strict too.
-            ASSERT(!strictMode() || cachedInfo->strictMode);
+            ASSERT(!strictMode() || (cachedInfo->lexicalScopeFeatures() & StrictModeLexicalFeature));
             JSTokenLocation endLocation;
 
             ConstructorKind constructorKind = static_cast<ConstructorKind>(cachedInfo->constructorKind);
@@ -2433,7 +2431,7 @@
             functionInfo.body = context.createFunctionMetadata(
                 startLocation, endLocation, startColumn, bodyEndColumn, 
                 functionKeywordStart, functionNameStart, parametersStart, 
-                cachedInfo->strictMode, constructorKind, functionSuperBinding,
+                cachedInfo->lexicalScopeFeatures(), constructorKind, functionSuperBinding,
                 cachedInfo->parameterCount,
                 mode, functionBodyType == ArrowFunctionBodyExpression);
             functionInfo.endOffset = cachedInfo->endFunctionOffset;

Modified: trunk/Source/_javascript_Core/parser/Parser.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/Parser.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -147,7 +147,7 @@
     WTF_MAKE_NONCOPYABLE(Scope);
 
 public:
-    Scope(const VM& vm, bool isFunction, bool isGenerator, bool strictMode, bool isArrowFunction, bool isAsyncFunction)
+    Scope(const VM& vm, LexicalScopeFeatures lexicalScopeFeatures, bool isFunction, bool isGenerator, bool isArrowFunction, bool isAsyncFunction)
         : m_vm(vm)
         , m_shadowsArguments(false)
         , m_usesEval(false)
@@ -156,7 +156,7 @@
         , m_needsSuperBinding(false)
         , m_allowsVarDeclarations(true)
         , m_allowsLexicalDeclarations(true)
-        , m_strictMode(strictMode)
+        , m_lexicalScopeFeatures(lexicalScopeFeatures)
         , m_isFunction(isFunction)
         , m_isGenerator(isGenerator)
         , m_isGeneratorBoundary(false)
@@ -756,8 +756,9 @@
             capturedVariables.add(impl);
         }
     }
-    void setStrictMode() { m_strictMode = true; }
-    bool strictMode() const { return m_strictMode; }
+    LexicalScopeFeatures lexicalScopeFeatures() const { return m_lexicalScopeFeatures; }
+    void setStrictMode() { m_lexicalScopeFeatures |= StrictModeLexicalFeature; }
+    bool strictMode() const { return m_lexicalScopeFeatures & StrictModeLexicalFeature; }
     bool isValidStrictMode() const { return m_isValidStrictMode; }
     bool shadowsArguments() const { return m_shadowsArguments; }
     void setHasNonSimpleParameterList()
@@ -780,7 +781,7 @@
     {
         ASSERT(m_isFunction);
         parameters.usesEval = m_usesEval;
-        parameters.strictMode = m_strictMode;
+        parameters.lexicalScopeFeatures = m_lexicalScopeFeatures;
         parameters.needsFullActivation = m_needsFullActivation;
         parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures;
         parameters.needsSuperBinding = m_needsSuperBinding;
@@ -804,7 +805,7 @@
     {
         ASSERT(m_isFunction);
         m_usesEval = info->usesEval;
-        m_strictMode = info->strictMode;
+        m_lexicalScopeFeatures = info->lexicalScopeFeatures();
         m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures;
         m_needsFullActivation = info->needsFullActivation;
         m_needsSuperBinding = info->needsSuperBinding;
@@ -904,7 +905,7 @@
     bool m_needsSuperBinding;
     bool m_allowsVarDeclarations;
     bool m_allowsLexicalDeclarations;
-    bool m_strictMode;
+    LexicalScopeFeatures m_lexicalScopeFeatures;
     bool m_isFunction;
     bool m_isGenerator;
     bool m_isGeneratorBoundary;
@@ -1325,19 +1326,19 @@
 
     ScopeRef pushScope()
     {
+        LexicalScopeFeatures lexicalScopeFeatures = NoLexicalFeatures;
         bool isFunction = false;
-        bool isStrict = false;
         bool isGenerator = false;
         bool isArrowFunction = false;
         bool isAsyncFunction = false;
         if (!m_scopeStack.isEmpty()) {
-            isStrict = m_scopeStack.last().strictMode();
+            lexicalScopeFeatures = m_scopeStack.last().lexicalScopeFeatures();
             isFunction = m_scopeStack.last().isFunction();
             isGenerator = m_scopeStack.last().isGenerator();
             isArrowFunction = m_scopeStack.last().isArrowFunction();
             isAsyncFunction = m_scopeStack.last().isAsyncFunction();
         }
-        m_scopeStack.constructAndAppend(m_vm, isFunction, isGenerator, isStrict, isArrowFunction, isAsyncFunction);
+        m_scopeStack.constructAndAppend(m_vm, lexicalScopeFeatures, isFunction, isGenerator, isArrowFunction, isAsyncFunction);
         return currentScope();
     }
 
@@ -1671,6 +1672,7 @@
     void endLoop() { currentScope()->endLoop(); }
     void startSwitch() { currentScope()->startSwitch(); }
     void endSwitch() { currentScope()->endSwitch(); }
+    LexicalScopeFeatures lexicalScopeFeatures() { return currentScope()->lexicalScopeFeatures(); }
     void setStrictMode() { currentScope()->setStrictMode(); }
     bool strictMode() { return currentScope()->strictMode(); }
     bool isValidStrictMode()
@@ -2177,6 +2179,7 @@
                                     parseResult.value().parameters,
                                     *m_source,
                                     parseResult.value().features,
+                                    currentScope()->lexicalScopeFeatures(),
                                     currentScope()->innerArrowFunctionFeatures(),
                                     parseResult.value().numConstants,
                                     WTFMove(m_moduleScopeData));

Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/ParserModes.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -306,6 +306,14 @@
     return true;
 }
 
+typedef uint8_t LexicalScopeFeatures;
+
+const LexicalScopeFeatures NoLexicalFeatures                           = 0;
+const LexicalScopeFeatures StrictModeLexicalFeature               = 1 << 0;
+
+const LexicalScopeFeatures AllLexicalFeatures = NoLexicalFeatures | StrictModeLexicalFeature;
+static_assert(AllLexicalFeatures <= 0b1111, "LexicalScopeFeatures must be 4bits");
+
 typedef uint16_t CodeFeatures;
 
 const CodeFeatures NoFeatures =                         0;
@@ -313,18 +321,17 @@
 const CodeFeatures ArgumentsFeature =              1 << 1;
 const CodeFeatures WithFeature =                   1 << 2;
 const CodeFeatures ThisFeature =                   1 << 3;
-const CodeFeatures StrictModeFeature =             1 << 4;
+const CodeFeatures NonSimpleParameterListFeature = 1 << 4;
 const CodeFeatures ShadowsArgumentsFeature =       1 << 5;
 const CodeFeatures ArrowFunctionFeature =          1 << 6;
-const CodeFeatures ArrowFunctionContextFeature =   1 << 7;
+const CodeFeatures AwaitFeature =                  1 << 7;
 const CodeFeatures SuperCallFeature =              1 << 8;
 const CodeFeatures SuperPropertyFeature =          1 << 9;
 const CodeFeatures NewTargetFeature =              1 << 10;
 const CodeFeatures NoEvalCacheFeature =            1 << 11;
-const CodeFeatures NonSimpleParameterListFeature = 1 << 12;
-const CodeFeatures AwaitFeature =                  1 << 13;
 
-const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature | ArrowFunctionFeature | ArrowFunctionContextFeature | SuperCallFeature | SuperPropertyFeature | NewTargetFeature | NoEvalCacheFeature | NonSimpleParameterListFeature | AwaitFeature;
+const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | ThisFeature | NonSimpleParameterListFeature | ShadowsArgumentsFeature | ArrowFunctionFeature | AwaitFeature | SuperCallFeature | SuperPropertyFeature | NewTargetFeature | NoEvalCacheFeature;
+static_assert(AllFeatures < (1 << 14), "CodeFeatures must be 14bits");
 
 typedef uint8_t InnerArrowFunctionCodeFeatures;
     

Modified: trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -42,7 +42,7 @@
     unsigned parameterCount;
     bool needsFullActivation;
     bool usesEval;
-    bool strictMode;
+    LexicalScopeFeatures lexicalScopeFeatures;
     bool needsSuperBinding;
     InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures;
     Vector<UniquedStringImpl*, 8> usedVariables;
@@ -78,6 +78,14 @@
         return token;
     }
 
+    LexicalScopeFeatures lexicalScopeFeatures() const
+    {
+        LexicalScopeFeatures features = NoLexicalFeatures;
+        if (strictMode)
+            features |= StrictModeLexicalFeature;
+        return features;
+    }
+
     bool needsFullActivation : 1;
     unsigned endFunctionOffset : 31;
     bool usesEval : 1;
@@ -122,7 +130,7 @@
     , endFunctionOffset(parameters.endFunctionOffset)
     , usesEval(parameters.usesEval)
     , lastTokenLine(parameters.lastTokenLine)
-    , strictMode(parameters.strictMode)
+    , strictMode(parameters.lexicalScopeFeatures & StrictModeLexicalFeature)
     , lastTokenStartOffset(parameters.lastTokenStartOffset)
     , expectedSuperBinding(static_cast<unsigned>(parameters.expectedSuperBinding))
     , lastTokenEndOffset(parameters.lastTokenEndOffset)

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (278587 => 278588)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -196,7 +196,7 @@
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     ExpressionType createGeneratorFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, const Identifier&) { return FunctionExpr; }
     ExpressionType createAsyncFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
-    int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
+    int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, unsigned, unsigned, int, int, int, LexicalScopeFeatures, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool) { return FunctionBodyResult; }
     ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     ExpressionType createMethodDefinition(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     void setFunctionNameStart(int, int) { }

Modified: trunk/Source/_javascript_Core/runtime/CachedBytecode.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/CachedBytecode.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/CachedBytecode.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -46,7 +46,7 @@
     ptrdiff_t offset = it->value.base();
     ASSERT(offset);
     copyLeafExecutables(bytecode.get());
-    m_updates.append(CacheUpdate::FunctionUpdate { offset, kind, { executable->features(), executable->hasCapturedVariables() }, WTFMove(bytecode->m_payload) });
+    m_updates.append(CacheUpdate::FunctionUpdate { offset, kind, { executable->features(), executable->lexicalScopeFeatures(), executable->hasCapturedVariables() }, WTFMove(bytecode->m_payload) });
 }
 
 void CachedBytecode::copyLeafExecutables(const CachedBytecode& bytecode)

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -1799,9 +1799,9 @@
     unsigned parameterCount() const { return m_parameterCount; }
 
     CodeFeatures features() const { return m_mutableMetadata.m_features; }
+    LexicalScopeFeatures lexicalScopeFeatures() const { return m_mutableMetadata.m_lexicalScopeFeatures; }
     SourceParseMode sourceParseMode() const { return m_sourceParseMode; }
 
-    unsigned isInStrictContext() const { return m_isInStrictContext; }
     unsigned hasCapturedVariables() const { return m_mutableMetadata.m_hasCapturedVariables; }
     unsigned isBuiltinFunction() const { return m_isBuiltinFunction; }
     unsigned isBuiltinDefaultClassConstructor() const { return m_isBuiltinDefaultClassConstructor; }
@@ -1826,7 +1826,6 @@
     CachedFunctionExecutableMetadata m_mutableMetadata;
 
     unsigned m_firstLineOffset : 31;
-    unsigned m_isInStrictContext : 1;
     unsigned m_lineCount : 31;
     unsigned m_isBuiltinFunction : 1;
     unsigned m_unlinkedFunctionNameStart : 31;
@@ -1902,6 +1901,7 @@
     unsigned evalContextType() const { return m_evalContextType; }
     unsigned hasTailCalls() const { return m_hasTailCalls; }
     unsigned hasCheckpoints() const { return m_hasCheckpoints; }
+    unsigned lexicalScopeFeatures() const { return m_lexicalScopeFeatures; }
     unsigned lineCount() const { return m_lineCount; }
     unsigned endColumn() const { return m_endColumn; }
 
@@ -1934,6 +1934,7 @@
     unsigned m_hasTailCalls : 1;
     unsigned m_codeType : 2;
     unsigned m_hasCheckpoints : 1;
+    unsigned m_lexicalScopeFeatures : 4;
 
     CodeFeatures m_features;
     SourceParseMode m_parseMode;
@@ -2115,9 +2116,13 @@
     , m_thisRegister(cachedCodeBlock.thisRegister())
     , m_scopeRegister(cachedCodeBlock.scopeRegister())
 
+    , m_numVars(cachedCodeBlock.numVars())
     , m_usesCallEval(cachedCodeBlock.usesCallEval())
+    , m_numCalleeLocals(cachedCodeBlock.numCalleeLocals())
     , m_isConstructor(cachedCodeBlock.isConstructor())
+    , m_numParameters(cachedCodeBlock.numParameters())
     , m_hasCapturedVariables(cachedCodeBlock.hasCapturedVariables())
+
     , m_isBuiltinFunction(cachedCodeBlock.isBuiltinFunction())
     , m_superBinding(cachedCodeBlock.superBinding())
     , m_scriptMode(cachedCodeBlock.scriptMode())
@@ -2133,6 +2138,7 @@
     , m_age(0)
     , m_hasCheckpoints(cachedCodeBlock.hasCheckpoints())
 
+    , m_lexicalScopeFeatures(cachedCodeBlock.lexicalScopeFeatures())
     , m_features(cachedCodeBlock.features())
     , m_parseMode(cachedCodeBlock.parseMode())
     , m_codeGenerationMode(cachedCodeBlock.codeGenerationMode())
@@ -2139,9 +2145,6 @@
 
     , m_lineCount(cachedCodeBlock.lineCount())
     , m_endColumn(cachedCodeBlock.endColumn())
-    , m_numVars(cachedCodeBlock.numVars())
-    , m_numCalleeLocals(cachedCodeBlock.numCalleeLocals())
-    , m_numParameters(cachedCodeBlock.numParameters())
 
     , m_sourceURLDirective(cachedCodeBlock.sourceURLDirective(decoder))
     , m_sourceMappingURLDirective(cachedCodeBlock.sourceMappingURLDirective(decoder))
@@ -2184,6 +2187,7 @@
 ALWAYS_INLINE void CachedFunctionExecutable::encode(Encoder& encoder, const UnlinkedFunctionExecutable& executable)
 {
     m_mutableMetadata.m_features = executable.m_features;
+    m_mutableMetadata.m_lexicalScopeFeatures = executable.m_lexicalScopeFeatures;
     m_mutableMetadata.m_hasCapturedVariables = executable.m_hasCapturedVariables;
 
     m_firstLineOffset = executable.m_firstLineOffset;
@@ -2200,7 +2204,6 @@
 
     m_sourceParseMode = executable.m_sourceParseMode;
 
-    m_isInStrictContext = executable.m_isInStrictContext;
     m_isBuiltinFunction = executable.m_isBuiltinFunction;
     m_isBuiltinDefaultClassConstructor = executable.m_isBuiltinDefaultClassConstructor;
     m_constructAbility = executable.m_constructAbility;
@@ -2234,7 +2237,7 @@
 ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& decoder, const CachedFunctionExecutable& cachedExecutable)
     : Base(decoder.vm(), decoder.vm().unlinkedFunctionExecutableStructure.get())
     , m_firstLineOffset(cachedExecutable.firstLineOffset())
-    , m_isInStrictContext(cachedExecutable.isInStrictContext())
+    , m_isGeneratedFromCache(true)
     , m_lineCount(cachedExecutable.lineCount())
     , m_hasCapturedVariables(cachedExecutable.hasCapturedVariables())
     , m_unlinkedFunctionNameStart(cachedExecutable.unlinkedFunctionNameStart())
@@ -2250,16 +2253,16 @@
     , m_parametersStartOffset(cachedExecutable.parametersStartOffset())
     , m_isCached(false)
     , m_typeProfilingStartOffset(cachedExecutable.typeProfilingStartOffset())
+    , m_needsClassFieldInitializer(cachedExecutable.needsClassFieldInitializer())
     , m_typeProfilingEndOffset(cachedExecutable.typeProfilingEndOffset())
     , m_parameterCount(cachedExecutable.parameterCount())
     , m_privateBrandRequirement(cachedExecutable.privateBrandRequirement())
     , m_features(cachedExecutable.features())
+    , m_constructorKind(cachedExecutable.constructorKind())
     , m_sourceParseMode(cachedExecutable.sourceParseMode())
-    , m_constructorKind(cachedExecutable.constructorKind())
+    , m_lexicalScopeFeatures(cachedExecutable.lexicalScopeFeatures())
     , m_functionMode(cachedExecutable.functionMode())
     , m_derivedContextType(cachedExecutable.derivedContextType())
-    , m_isGeneratedFromCache(true)
-    , m_needsClassFieldInitializer(cachedExecutable.needsClassFieldInitializer())
     , m_unlinkedCodeBlockForCall()
     , m_unlinkedCodeBlockForConstruct()
 
@@ -2320,6 +2323,7 @@
     m_numCalleeLocals = codeBlock.m_numCalleeLocals;
     m_numParameters = codeBlock.m_numParameters;
     m_features = codeBlock.m_features;
+    m_lexicalScopeFeatures = codeBlock.m_lexicalScopeFeatures;
     m_parseMode = codeBlock.m_parseMode;
     m_codeGenerationMode = codeBlock.m_codeGenerationMode;
     m_codeType = codeBlock.m_codeType;

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.h (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -46,6 +46,7 @@
 // cache, since this will only be filled in when we parse the function
 struct CachedFunctionExecutableMetadata {
     CodeFeatures m_features;
+    LexicalScopeFeatures m_lexicalScopeFeatures;
     bool m_hasCapturedVariables;
 };
 

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -87,11 +87,9 @@
     bool endColumnIsOnStartLine = !lineCount;
     unsigned unlinkedEndColumn = rootNode->endColumn();
     unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
-    unsigned arrowContextFeature = isArrowFunctionContext ? ArrowFunctionContextFeature : 0;
     if (executable)
-        executable->recordParse(rootNode->features() | arrowContextFeature, rootNode->hasCapturedVariables(), rootNode->lastLine(), endColumn);
+        executable->recordParse(rootNode->features(), rootNode->lexicalScopeFeatures(), rootNode->hasCapturedVariables(), rootNode->lastLine(), endColumn);
 
-    ECMAMode ecmaMode = rootNode->features() & StrictModeFeature ? ECMAMode::strict() : ECMAMode::sloppy();
     NeedsClassFieldInitializer needsClassFieldInitializer = NeedsClassFieldInitializer::No;
     PrivateBrandRequirement privateBrandRequirement = PrivateBrandRequirement::None;
     if constexpr (std::is_same_v<ExecutableType, DirectEvalExecutable>) {
@@ -101,7 +99,7 @@
     ExecutableInfo executableInfo(false, privateBrandRequirement, false, ConstructorKind::None, scriptMode, SuperBinding::NotNeeded, CacheTypes<UnlinkedCodeBlockType>::parseMode, derivedContextType, needsClassFieldInitializer, isArrowFunctionContext, false, evalContextType);
 
     UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(vm, executableInfo, codeGenerationMode);
-    unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), lineCount, unlinkedEndColumn);
+    unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->lexicalScopeFeatures(), rootNode->hasCapturedVariables(), lineCount, unlinkedEndColumn);
     if (!source.provider()->sourceURLDirective().isNull())
         unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURLDirective());
     if (!source.provider()->sourceMappingURLDirective().isNull())
@@ -110,7 +108,7 @@
     RefPtr<TDZEnvironmentLink> parentVariablesUnderTDZ;
     if (variablesUnderTDZ)
         parentVariablesUnderTDZ = TDZEnvironmentLink::create(vm.m_compactVariableMap->get(*variablesUnderTDZ), nullptr);
-    error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, parentVariablesUnderTDZ, privateNameEnvironment, ecmaMode);
+    error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, parentVariablesUnderTDZ, privateNameEnvironment);
 
     if (error.isValid())
         return nullptr;
@@ -167,7 +165,7 @@
         unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn().oneBasedInt();
         bool endColumnIsOnStartLine = !lineCount;
         unsigned endColumn = unlinkedCodeBlock->endColumn() + (endColumnIsOnStartLine ? startColumn : 1);
-        executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), source.firstLine().oneBasedInt() + lineCount, endColumn);
+        executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->lexicalScopeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), source.firstLine().oneBasedInt() + lineCount, endColumn);
         if (unlinkedCodeBlock->sourceURLDirective())
             source.provider()->setSourceURLDirective(unlinkedCodeBlock->sourceURLDirective());
         if (unlinkedCodeBlock->sourceMappingURLDirective())

Modified: trunk/Source/_javascript_Core/runtime/ECMAMode.h (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/ECMAMode.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/ECMAMode.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -37,6 +37,7 @@
 
 public:
     static constexpr ECMAMode fromByte(uint8_t byte) { return ECMAMode(byte); }
+    static constexpr ECMAMode fromBool(bool isStrict) { return isStrict ? strict() : sloppy(); }
     static constexpr ECMAMode strict() { return ECMAMode(StrictMode); }
     static constexpr ECMAMode sloppy() { return ECMAMode(SloppyMode); }
 

Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -35,7 +35,7 @@
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(FunctionExecutable) };
 
 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic, bool isInsideOrdinaryFunction)
-    : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->derivedContextType(), false, isInsideOrdinaryFunction || !unlinkedExecutable->isArrowFunction(), EvalContextType::None, intrinsic)
+    : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->lexicalScopeFeatures(), unlinkedExecutable->derivedContextType(), false, isInsideOrdinaryFunction || !unlinkedExecutable->isArrowFunction(), EvalContextType::None, intrinsic)
     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
 {
     RELEASE_ASSERT(!source.isNull());

Modified: trunk/Source/_javascript_Core/runtime/GlobalExecutable.h (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/GlobalExecutable.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/GlobalExecutable.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -40,9 +40,9 @@
     unsigned lastLine() const { return m_lastLine; }
     unsigned endColumn() const { return m_endColumn; }
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
+    void recordParse(CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn)
     {
-        Base::recordParse(features, hasCapturedVariables);
+        Base::recordParse(features, lexicalScopeFeatures, hasCapturedVariables);
         m_lastLine = lastLine;
         m_endColumn = endColumn;
         ASSERT(endColumn != UINT_MAX);
@@ -50,7 +50,7 @@
 
 protected:
     GlobalExecutable(Structure* structure, VM& vm, const SourceCode& sourceCode, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
-        : Base(structure, vm, sourceCode, isInStrictContext, derivedContextType, isInArrowFunctionContext, isInsideOrdinaryFunction, evalContextType, intrinsic)
+        : Base(structure, vm, sourceCode, isInStrictContext ? StrictModeLexicalFeature : NoLexicalFeatures, derivedContextType, isInArrowFunctionContext, isInsideOrdinaryFunction, evalContextType, intrinsic)
     {
     }
 

Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.cpp	2021-06-08 01:43:14 UTC (rev 278588)
@@ -46,11 +46,12 @@
 
 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ScriptExecutable) };
 
-ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
+ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, LexicalScopeFeatures lexicalScopeFeatures, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
     : ExecutableBase(vm, structure)
     , m_source(source)
     , m_intrinsic(intrinsic)
-    , m_features(isInStrictContext ? StrictModeFeature : 0)
+    , m_features(NoFeatures)
+    , m_lexicalScopeFeatures(lexicalScopeFeatures)
     , m_hasCapturedVariables(false)
     , m_neverInline(false)
     , m_neverOptimize(false)
@@ -328,6 +329,7 @@
             executable->parseMode());
     recordParse(
         executable->m_unlinkedExecutable->features(), 
+        executable->m_unlinkedExecutable->lexicalScopeFeatures(),
         executable->m_unlinkedExecutable->hasCapturedVariables(),
         lastLine(), endColumn()); 
     if (!unlinkedCodeBlock) {
@@ -522,15 +524,15 @@
     return source().length() - 1;
 }
 
-void ScriptExecutable::recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
+void ScriptExecutable::recordParse(CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn)
 {
     switch (type()) {
     case FunctionExecutableType:
         // Since UnlinkedFunctionExecutable holds the information to calculate lastLine and endColumn, we do not need to remember them in ScriptExecutable's fields.
-        jsCast<FunctionExecutable*>(this)->recordParse(features, hasCapturedVariables);
+        jsCast<FunctionExecutable*>(this)->recordParse(features, lexicalScopeFeatures, hasCapturedVariables);
         return;
     default:
-        jsCast<GlobalExecutable*>(this)->recordParse(features, hasCapturedVariables, lastLine, endColumn);
+        jsCast<GlobalExecutable*>(this)->recordParse(features, lexicalScopeFeatures, hasCapturedVariables, lastLine, endColumn);
         return;
     }
 }

Modified: trunk/Source/_javascript_Core/runtime/ScriptExecutable.h (278587 => 278588)


--- trunk/Source/_javascript_Core/runtime/ScriptExecutable.h	2021-06-08 01:29:31 UTC (rev 278587)
+++ trunk/Source/_javascript_Core/runtime/ScriptExecutable.h	2021-06-08 01:43:14 UTC (rev 278588)
@@ -62,7 +62,7 @@
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
     DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
     EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); }
-    bool isInStrictContext() const { return m_features & StrictModeFeature; }
+    bool isInStrictContext() const { return m_lexicalScopeFeatures & StrictModeLexicalFeature; }
     bool usesNonSimpleParameterList() const { return m_features & NonSimpleParameterListFeature; }
 
     void setNeverInline(bool value) { m_neverInline = value; }
@@ -85,7 +85,7 @@
         
     DECLARE_EXPORT_INFO;
 
-    void recordParse(CodeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn);
+    void recordParse(CodeFeatures, LexicalScopeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn);
     void installCode(CodeBlock*);
     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, Exception*&);
@@ -128,11 +128,12 @@
     TemplateObjectMap& ensureTemplateObjectMap(VM&);
 
 protected:
-    ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType, Intrinsic);
+    ScriptExecutable(Structure*, VM&, const SourceCode&, LexicalScopeFeatures, DerivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType, Intrinsic);
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables)
+    void recordParse(CodeFeatures features, LexicalScopeFeatures lexicalScopeFeatures, bool hasCapturedVariables)
     {
         m_features = features;
+        m_lexicalScopeFeatures = lexicalScopeFeatures;
         m_hasCapturedVariables = hasCapturedVariables;
     }
 
@@ -142,6 +143,7 @@
     Intrinsic m_intrinsic { NoIntrinsic };
     bool m_didTryToEnterInLoop { false };
     CodeFeatures m_features;
+    unsigned m_lexicalScopeFeatures : 4;
     OptionSet<CodeGenerationMode> m_codeGenerationModeForGeneratorBody;
     bool m_hasCapturedVariables : 1;
     bool m_neverInline : 1;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to