| AbstractScopePtr.cpp |
|
1635 |
- |
| AbstractScopePtr.h |
|
2472 |
- |
| align_stack_comment.py |
Usage: align_stack_comment.py FILE
This script aligns the stack transition comment in BytecodeEmitter and
its helper classes.
The stack transition comment looks like the following:
// [stack] VAL1 VAL2 VAL3
|
2980 |
- |
| AsyncEmitter.cpp |
|
5157 |
- |
| AsyncEmitter.h |
|
5594 |
- |
| BytecodeCompiler.cpp |
|
62217 |
- |
| BytecodeCompiler.h |
Structure of all of the support classes.
Parser: described in Parser.h.
BytecodeCompiler.cpp: BytecodeCompiler.h
This is the "driver", the high-level operations like "compile this source to
bytecode". It calls the parser, bytecode emitter, etc.
ParseContext.h and SharedContext.h: Both have similar purposes. They're split
because ParseContext contains information used only by the parser, and
SharedContext contains information used by both the parser and
BytecodeEmitter.
SharedContext.h: class Directives: this contains boolean flags for tracking
if we're in "use strict" code. The "use strict" bit is stored in
SharedContext, and additionally, the full Directives class is stored in
ParseContext - if a direcive is encountered while parsing, this is updated,
and checked in GeneralParser::functionDefinition, and if it changed, the
whole function is re-parsed with the new flags.
SharedContext.h: abstract class SharedContext: This class contains two
different groups of flags:
Parse context information. This is information conceptually "passed down"
into parsing sub-nodes. This is like "are we parsing strict code?", and so
the parser can make decisions of how to parse based off that.
Gathered-while-parsing information. This is information conceptually
"returned up" from parsing sub-nodes. This is like "did we see a use strict
directive"?
Additionally, subclasses (GlobalSharedContext, ModuleSharedContext,
EvalSharedContext, and FunctionBox) contain binding information, scope
information, and other such bits of data.
ParseContext.h: class UsedNameTracker: Track which bindings are used in which
scopes. This helps determine which bindings are closed-over, which affects
how they're stored; and whether special bindings like `this` and `arguments`
can be optimized away.
ParseContext.h: class ParseContext: Extremely complex class that serves a lot
of purposes, but it's a single class - essentially no derived classes - so
it's a little easier to comprehend all at once. (SourceParseContext does
derive from ParseContext, but they does nothing except adjust the
constructor's arguments).
Note it uses a thing called Nestable, which implements a stack of objects:
you can push (and pop) instances to a stack (linked list) as you parse
further into the parse tree. You may push to this stack via calling the
constructor with a GeneralParser as an argument (usually `this`), which
pushes itself onto `this->pc` (so it does get assigned/pushed, even though no
assignment ever appears directly in the parser)
ParseContext contains a pointer to a SharedContext.
There's a decent chunk of flags/data collection in here too, some "pass-down"
data and some "return-up" data.
ParseContext also contains a significant number of *sub*-Nestables as fields
of itself (nestables inside nestables). Note you also push/pop to these via
passing `Parser->pc`, which the constructor of the sub-nestable knows which
ParseContext field to push to. The sub-nestables are:
ParseContext::Statement: stack of statements.
`if (x) { while (true) { try { ..stack of [if, while, try].. } ... } }`
ParseContext::LabelStatement: interspersed in Statement stack, for labeled
statements, for e.g. `label: while (true) { break label; }`
ParseContext::ClassStatement: interspersed in Statement stack, for classes
the parser is currently inside of.
ParseContext::Scope: Set of variables in each scope (stack of sets):
`{ let a; let b; { let c; } }`
(this gets complicated with `var`, etc., check the class for docs)
|
11847 |
- |
| BytecodeControlStructures.cpp |
|
13040 |
- |
| BytecodeControlStructures.h |
|
6445 |
- |
| BytecodeEmitter.cpp |
JS bytecode generation.
|
397930 |
- |
| BytecodeEmitter.h |
JS bytecode generation. |
46512 |
- |
| BytecodeOffset.h |
namespace frontend |
3458 |
- |
| BytecodeSection.cpp |
|
6374 |
- |
| BytecodeSection.h |
|
12513 |
- |
| CallOrNewEmitter.cpp |
|
9668 |
- |
| CallOrNewEmitter.h |
|
12691 |
- |
| CForEmitter.cpp |
|
4939 |
- |
| CForEmitter.h |
|
5295 |
- |
| CompilationStencil.h |
|
94664 |
- |
| DecoratorEmitter.cpp |
|
45884 |
- |
| DecoratorEmitter.h |
namespace js::frontend |
2748 |
- |
| DefaultEmitter.cpp |
|
1692 |
- |
| DefaultEmitter.h |
namespace frontend |
1563 |
- |
| DestructuringFlavor.h |
namespace frontend |
575 |
- |
| DoWhileEmitter.cpp |
|
1487 |
- |
| DoWhileEmitter.h |
namespace frontend |
1851 |
- |
| EitherParser.h |
A variant-like class abstracting operations on a Parser with a given
ParseHandler but unspecified character type.
|
1653 |
- |
| ElemOpEmitter.cpp |
|
6405 |
- |
| ElemOpEmitter.h |
|
6941 |
- |
| EmitterScope.cpp |
static |
38777 |
- |
| EmitterScope.h |
|
9421 |
- |
| ErrorReporter.h |
|
11293 |
- |
| ExpressionStatementEmitter.cpp |
|
1373 |
- |
| ExpressionStatementEmitter.h |
frontend_ExpressionStatementEmitter_h |
1919 |
- |
| FoldConstants.cpp |
|
52348 |
- |
| FoldConstants.h |
namespace frontend |
1798 |
- |
| ForInEmitter.cpp |
|
4247 |
- |
| ForInEmitter.h |
namespace frontend |
3522 |
- |
| ForOfEmitter.cpp |
|
8512 |
- |
| ForOfEmitter.h |
namespace frontend |
3764 |
- |
| ForOfLoopControl.cpp |
|
9667 |
- |
| ForOfLoopControl.h |
namespace frontend |
3921 |
- |
| FrontendContext.cpp |
OOMs are non-deterministic, especially across different execution modes
(e.g. interpreter vs JIT). When doing differential testing, print to
stderr so that the fuzzers can detect this.
|
10538 |
- |
| FrontendContext.h |
|
9002 |
- |
| FullParseHandler.h |
new_ methods for creating parse nodes. These report OOM on context. |
45061 |
- |
| FunctionEmitter.cpp |
|
25036 |
- |
| FunctionEmitter.h |
|
14933 |
- |
| FunctionSyntaxKind.h |
namespace frontend |
940 |
- |
| GenerateReservedWords.py |
|
5573 |
- |
| IfEmitter.cpp |
= ConditionKind::Positive |
7185 |
- |
| IfEmitter.h |
|
9586 |
- |
| IteratorKind.h |
namespace js::frontend |
408 |
- |
| JumpList.cpp |
|
1339 |
- |
| JumpList.h |
namespace frontend |
2641 |
- |
| LabelEmitter.cpp |
|
882 |
- |
| LabelEmitter.h |
namespace frontend |
1500 |
- |
| LexicalScopeEmitter.cpp |
|
1538 |
- |
| LexicalScopeEmitter.h |
namespace frontend |
2815 |
- |
| ModuleSharedContext.h |
frontend_ModuleSharedContext_h |
1238 |
- |
| moz.build |
|
2555 |
- |
| NameAnalysisTypes.h |
|
12516 |
- |
| NameCollections.h |
|
13316 |
- |
| NameFunctions.cpp |
Test whether a ParseNode represents a function invocation |
18476 |
- |
| NameFunctions.h |
namespace frontend |
626 |
- |
| NameOpEmitter.cpp |
|
16418 |
- |
| NameOpEmitter.h |
namespace frontend |
5049 |
- |
| ObjectEmitter.cpp |
isStatic_ = |
26092 |
- |
| ObjectEmitter.h |
|
30529 |
- |
| ObjLiteral.cpp |
|
17361 |
- |
| ObjLiteral.h |
|
25453 |
- |
| OptionalEmitter.cpp |
= Kind::Other |
3770 |
- |
| OptionalEmitter.h |
|
7323 |
- |
| ParseContext-inl.h |
|
5962 |
- |
| ParseContext.cpp |
|
27208 |
- |
| ParseContext.h |
The struct ParseContext stores information about the current parsing context,
which is part of the parser state (see the field Parser::pc). The current
parsing context is either the global context, or the function currently being
parsed. When the parser encounters a function definition, it creates a new
ParseContext, makes it the new current context.
|
25286 |
- |
| ParseNode.cpp |
Allocate a ParseNode from parser's node freelist or, failing that, from
cx's temporary arena.
|
14027 |
- |
| ParseNode.h |
|
90612 |
- |
| ParseNodeVerify.cpp |
|
1380 |
- |
| ParseNodeVerify.h |
namespace frontend |
1405 |
- |
| ParseNodeVisitor.h |
Utility class for walking a JS AST.
Simple usage:
class HowTrueVisitor : public ParseNodeVisitor<HowTrueVisitor> {
public:
bool visitTrueExpr(BooleanLiteral* pn) {
std::cout << "How true.\n";
return true;
}
bool visitClassDecl(ClassNode* pn) {
// The base-class implementation of each visit method
// simply visits the node's children. So the subclass
// gets to decide whether to descend into a subtree
// and can do things either before or after:
std::cout << "How classy.\n";
return ParseNodeVisitor::visitClassDecl(pn);
}
};
HowTrueVisitor v;
v.visit(programRootNode); // walks the entire tree
A ParseNodeVisitor can modify nodes, but it can't replace the current node
with a different one; for that, use a RewritingParseNodeVisitor.
Note that the Curiously Recurring Template Pattern is used for performance,
as it eliminates the need for virtual method calls. Some rough testing shows
about a 12% speedup in the FoldConstants.cpp pass.
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
|
4332 |
- |
| Parser-macros.h |
frontend_Parser_macros_h |
785 |
- |
| Parser.cpp |
JS parser.
This is a recursive-descent parser for the JavaScript language specified by
"The ECMAScript Language Specification" (Standard ECMA-262). It uses
lexical and semantic feedback to disambiguate non-LL(1) structures. It
generates trees of nodes induced by the recursive parsing (not precise
syntax trees, see Parser.h). After tree construction, it rewrites trees to
fold constants and evaluate compile-time expressions.
This parser attempts no error recovery.
|
416132 |
- |
| Parser.h |
JS parser. |
76213 |
- |
| ParserAtom.cpp |
static |
42819 |
- |
| ParserAtom.h |
|
30793 |
- |
| PrivateOpEmitter.cpp |
|
8693 |
- |
| PrivateOpEmitter.h |
|
6857 |
- |
| PropOpEmitter.cpp |
|
6224 |
- |
| PropOpEmitter.h |
|
6857 |
- |
| ReservedWordReader.py |
|
1278 |
- |
| ReservedWords.h |
A higher-order macro for enumerating reserved word tokens. |
5340 |
- |
| ScopeBindingCache.h |
|
11830 |
- |
| ScopeIndex.h |
namespace js |
800 |
- |
| ScriptIndex.h |
namespace frontend |
991 |
- |
| SelfHostedIter.h |
namespace js::frontend |
963 |
- |
| SharedContext-inl.h |
|
570 |
- |
| SharedContext.cpp |
|
13159 |
- |
| SharedContext.h |
The struct SharedContext is part of the current parser context (see
ParseContext). It stores information that is reused between the parser and
the bytecode emitter.
|
25363 |
- |
| SourceNotes.cpp |
|
433 |
- |
| SourceNotes.h |
[SMDOC] Source Notes
Source notes are generated along with bytecode for associating line/column
to opcode, and annotating opcode as breakpoint for debugging.
A source note is a uint8_t with 4 bits of type and 4 bits of offset from
the pc of the previous note. If 4 bits of offset aren't enough, extended
delta notes (XDelta) consisting of 1 set high order bit followed by 7 offset
bits are emitted before the next note.
Source Note Extended Delta
+7-6-5-4+3-2-1-0+ +7+6-5-4-3-2-1-0+
| type | delta | |1| ext-delta |
+-------+-------+ +-+-------------+
Extended Delta with `ext-delta == 0` is used as terminator, which is
padded between the end of source notes and the next notes in the
ImmutableScriptData.
Terminator
+7+6-5-4-3-2-1-0+
|1|0 0 0 0 0 0 0|
+-+-------------+
Some notes have operand offsets encoded immediately after them. Each operand
is encoded either in single-byte or 4-bytes, depending on the range.
Single-byte Operand (0 <= operand <= 127)
+7+6-5-4-3-2-1-0+
|0| operand |
+-+-------------+
4-bytes Operand (128 <= operand)
(operand_3 << 24) | (operand_2 << 16) | (operand_1 << 8) | operand_0
+7-6-5-4-3-2-1-0+ +7-6-5-4-3-2-1-0+ +7-6-5-4-3-2-1-0+ +7-6-5-4-3-2-1-0+
|1| operand_3 | | operand_2 | | operand_1 | | operand_0 |
+---------------+ +---------------+ +---------------+ +---------------+
NB: the js::SrcNote::specs_ array is indexed by this enum, so its
initializers need to match the order here.
|
16292 |
- |
| Stencil.cpp |
|
206959 |
- |
| Stencil.h |
|
44757 |
- |
| StencilXdr.cpp |
|
52389 |
- |
| StencilXdr.h |
|
7967 |
- |
| SwitchEmitter.cpp |
|
10790 |
- |
| SwitchEmitter.h |
|
14038 |
- |
| SyntaxParseHandler.h |
|
29534 |
- |
| TaggedParserAtomIndexHasher.h |
|
1178 |
- |
| TDZCheckCache.cpp |
|
1885 |
- |
| TDZCheckCache.h |
namespace frontend |
2183 |
- |
| Token.h |
Token-affiliated data structures except for TokenKind (defined in its own
header).
|
6765 |
- |
| TokenKind.h |
List of token kinds and their ranges.
The format for each line is:
MACRO(<TOKEN_KIND_NAME>, <DESCRIPTION>)
or
RANGE(<TOKEN_RANGE_NAME>, <TOKEN_KIND_NAME>)
where ;
<TOKEN_KIND_NAME> is a legal C identifier of the token, that will be used in
the JS engine source.
<DESCRIPTION> is a string that describe about the token, and will be used in
error message.
<TOKEN_RANGE_NAME> is a legal C identifier of the range that will be used to
JS engine source. It should end with `First` or `Last`. This is used to check
TokenKind by range-testing:
BinOpFirst <= tt && tt <= BinOpLast
Second argument of `RANGE` is the actual value of the <TOKEN_RANGE_NAME>,
should be same as one of <TOKEN_KIND_NAME> in other `MACRO`s.
To use this macro, define two macros for `MACRO` and `RANGE`, and pass them
as arguments.
#define EMIT_TOKEN(name, desc) ...
#define EMIT_RANGE(name, value) ...
FOR_EACH_TOKEN_KIND_WITH_RANGE(EMIT_TOKEN, EMIT_RANGE)
#undef EMIT_TOKEN
#undef EMIT_RANGE
If you don't need range data, use FOR_EACH_TOKEN_KIND instead.
#define EMIT_TOKEN(name, desc) ...
FOR_EACH_TOKEN_KIND(EMIT_TOKEN)
#undef EMIT_TOKEN
Note that this list does not contain Limit.
|
18375 |
- |
| TokenStream.cpp |
|
122941 |
- |
| TokenStream.h |
Streaming access to the raw tokens of JavaScript source.
Because JS tokenization is context-sensitive -- a '/' could be either a
regular expression *or* a division operator depending on context -- the
various token stream classes are mostly not useful outside of the Parser
where they reside. We should probably eventually merge the two concepts.
|
109536 |
- |
| TryEmitter.cpp |
= Nothing() |
8986 |
- |
| TryEmitter.h |
|
7941 |
- |
| TypedIndex.h |
|
962 |
- |
| UsedNameTracker.h |
|
9736 |
- |
| UsingEmitter.cpp |
|
36391 |
- |
| UsingEmitter.h |
|
8167 |
- |
| ValueUsage.h |
namespace frontend |
979 |
- |
| WhileEmitter.cpp |
|
2559 |
- |
| WhileEmitter.h |
namespace frontend |
2740 |
- |