source: webkit/trunk/Source/JavaScriptCore/parser/SourceProviderCacheItem.h

Last change on this file was 278588, checked in by Alexey Shvayka, 4 years ago

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

Reviewed by Keith Miller.

Before this , 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 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):

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1/*
2* Copyright (C) 2011 Apple Inc. All rights reserved.
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions
6* are met:
7* 1. Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* 2. Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12*
13* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23* THE POSSIBILITY OF SUCH DAMAGE.
24*/
25
26#pragma once
27
28#include "ParserModes.h"
29#include "ParserTokens.h"
30#include <wtf/Vector.h>
31#include <wtf/text/UniquedStringImpl.h>
32#include <wtf/text/WTFString.h>
33
34namespace JSC {
35
36struct SourceProviderCacheItemCreationParameters {
37unsigned lastTokenLine;
38unsigned lastTokenStartOffset;
39unsigned lastTokenEndOffset;
40unsigned lastTokenLineStartOffset;
41unsigned endFunctionOffset;
42unsigned parameterCount;
43bool needsFullActivation;
44bool usesEval;
45LexicalScopeFeatures lexicalScopeFeatures;
46bool needsSuperBinding;
47InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures;
48Vector<UniquedStringImpl*, 8> usedVariables;
49bool isBodyArrowExpression { false };
50JSTokenType tokenType { CLOSEBRACE };
51ConstructorKind constructorKind;
52SuperBinding expectedSuperBinding;
53};
54
55#if COMPILER(MSVC)
56#pragma warning(push)
57#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
58#endif
59
60DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(SourceProviderCacheItem);
61class SourceProviderCacheItem {
62WTF_MAKE_STRUCT_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(SourceProviderCacheItem);
63public:
64static std::unique_ptr<SourceProviderCacheItem> create(const SourceProviderCacheItemCreationParameters&);
65~SourceProviderCacheItem();
66
67JSToken endFunctionToken() const
68{
69JSToken token;
70token.m_type = isBodyArrowExpression ? static_cast<JSTokenType>(tokenType) : CLOSEBRACE;
71token.m_data.offset = lastTokenStartOffset;
72token.m_location.startOffset = lastTokenStartOffset;
73token.m_location.endOffset = lastTokenEndOffset;
74token.m_location.line = lastTokenLine;
75token.m_location.lineStartOffset = lastTokenLineStartOffset;
76// token.m_location.sourceOffset is initialized once by the client. So,
77// we do not need to set it here.
78return token;
79}
80
81LexicalScopeFeatures lexicalScopeFeatures() const
82{
83LexicalScopeFeatures features = NoLexicalFeatures;
84if (strictMode)
85features |= StrictModeLexicalFeature;
86return features;
87}
88
89bool needsFullActivation : 1;
90unsigned endFunctionOffset : 31;
91bool usesEval : 1;
92unsigned lastTokenLine : 31;
93bool strictMode : 1;
94unsigned lastTokenStartOffset : 31;
95unsigned expectedSuperBinding : 1; // SuperBinding
96unsigned lastTokenEndOffset: 31;
97bool needsSuperBinding: 1;
98unsigned parameterCount : 31;
99unsigned lastTokenLineStartOffset : 31;
100bool isBodyArrowExpression : 1;
101unsigned usedVariablesCount;
102unsigned tokenType : 24; // JSTokenType
103unsigned innerArrowFunctionFeatures : 6; // InnerArrowFunctionCodeFeatures
104unsigned constructorKind : 2; // ConstructorKind
105
106PackedPtr<UniquedStringImpl>* usedVariables() const { return const_cast<PackedPtr<UniquedStringImpl>*>(m_variables); }
107
108private:
109SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters&);
110
111PackedPtr<UniquedStringImpl> m_variables[0];
112};
113
114inline SourceProviderCacheItem::~SourceProviderCacheItem()
115{
116for (unsigned i = 0; i < usedVariablesCount; ++i)
117m_variables[i]->deref();
118}
119
120inline std::unique_ptr<SourceProviderCacheItem> SourceProviderCacheItem::create(const SourceProviderCacheItemCreationParameters& parameters)
121{
122size_t variableCount = parameters.usedVariables.size();
123size_t objectSize = sizeof(SourceProviderCacheItem) + sizeof(UniquedStringImpl*) * variableCount;
124void* slot = SourceProviderCacheItemMalloc::malloc(objectSize);
125return std::unique_ptr<SourceProviderCacheItem>(new (slot) SourceProviderCacheItem(parameters));
126}
127
128inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters& parameters)
129: needsFullActivation(parameters.needsFullActivation)
130, endFunctionOffset(parameters.endFunctionOffset)
131, usesEval(parameters.usesEval)
132, lastTokenLine(parameters.lastTokenLine)
133, strictMode(parameters.lexicalScopeFeatures & StrictModeLexicalFeature)
134, lastTokenStartOffset(parameters.lastTokenStartOffset)
135, expectedSuperBinding(static_cast<unsigned>(parameters.expectedSuperBinding))
136, lastTokenEndOffset(parameters.lastTokenEndOffset)
137, needsSuperBinding(parameters.needsSuperBinding)
138, parameterCount(parameters.parameterCount)
139, lastTokenLineStartOffset(parameters.lastTokenLineStartOffset)
140, isBodyArrowExpression(parameters.isBodyArrowExpression)
141, usedVariablesCount(parameters.usedVariables.size())
142, tokenType(static_cast<unsigned>(parameters.tokenType))
143, innerArrowFunctionFeatures(static_cast<unsigned>(parameters.innerArrowFunctionFeatures))
144, constructorKind(static_cast<unsigned>(parameters.constructorKind))
145{
146ASSERT(tokenType == static_cast<unsigned>(parameters.tokenType));
147ASSERT(innerArrowFunctionFeatures == static_cast<unsigned>(parameters.innerArrowFunctionFeatures));
148ASSERT(constructorKind == static_cast<unsigned>(parameters.constructorKind));
149ASSERT(expectedSuperBinding == static_cast<unsigned>(parameters.expectedSuperBinding));
150for (unsigned i = 0; i < usedVariablesCount; ++i) {
151auto* pointer = parameters.usedVariables[i];
152pointer->ref();
153m_variables[i] = pointer;
154}
155}
156
157#if COMPILER(MSVC)
158#pragma warning(pop)
159#endif
160
161} // namespace JSC
Note: See TracBrowser for help on using the repository browser.