1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef frontend_SharedContext_h
8 #define frontend_SharedContext_h
9
10 #include "mozilla/Assertions.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/Maybe.h"
13
14 #include "jstypes.h"
15
16 #include "frontend/AbstractScopePtr.h" // ScopeIndex
17 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
18 #include "frontend/ParseNode.h"
19 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
20 #include "frontend/ScriptIndex.h" // ScriptIndex
21 #include "js/WasmModule.h" // JS::WasmModule
22 #include "vm/FunctionFlags.h" // js::FunctionFlags
23 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
24 #include "vm/JSFunction.h"
25 #include "vm/JSScript.h"
26 #include "vm/Scope.h"
27 #include "vm/SharedStencil.h"
28
29 namespace js {
30 namespace frontend {
31
32 struct CompilationState;
33 class ParseContext;
34 class ScriptStencil;
35 struct ScopeContext;
36
37 enum class StatementKind : uint8_t {
38 Label,
39 Block,
40 If,
41 Switch,
42 With,
43 Catch,
44 Try,
45 Finally,
46 ForLoopLexicalHead,
47 ForLoop,
48 ForInLoop,
49 ForOfLoop,
50 DoLoop,
51 WhileLoop,
52 Class,
53
54 // Used only by BytecodeEmitter.
55 Spread,
56 YieldStar,
57 };
58
StatementKindIsLoop(StatementKind kind)59 static inline bool StatementKindIsLoop(StatementKind kind) {
60 return kind == StatementKind::ForLoop || kind == StatementKind::ForInLoop ||
61 kind == StatementKind::ForOfLoop || kind == StatementKind::DoLoop ||
62 kind == StatementKind::WhileLoop || kind == StatementKind::Spread ||
63 kind == StatementKind::YieldStar;
64 }
65
StatementKindIsUnlabeledBreakTarget(StatementKind kind)66 static inline bool StatementKindIsUnlabeledBreakTarget(StatementKind kind) {
67 return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
68 }
69
70 // List of directives that may be encountered in a Directive Prologue
71 // (ES5 15.1).
72 class Directives {
73 bool strict_;
74 bool asmJS_;
75
76 public:
Directives(bool strict)77 explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
78 explicit Directives(ParseContext* parent);
79
setStrict()80 void setStrict() { strict_ = true; }
strict()81 bool strict() const { return strict_; }
82
setAsmJS()83 void setAsmJS() { asmJS_ = true; }
asmJS()84 bool asmJS() const { return asmJS_; }
85
86 Directives& operator=(Directives rhs) {
87 strict_ = rhs.strict_;
88 asmJS_ = rhs.asmJS_;
89 return *this;
90 }
91 bool operator==(const Directives& rhs) const {
92 return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
93 }
94 bool operator!=(const Directives& rhs) const { return !(*this == rhs); }
95 };
96
97 // The kind of this-binding for the current scope. Note that arrow functions
98 // have a lexical this-binding so their ThisBinding is the same as the
99 // ThisBinding of their enclosing scope and can be any value. Derived
100 // constructors require TDZ checks when accessing the binding.
101 enum class ThisBinding : uint8_t {
102 Global,
103 Module,
104 Function,
105 DerivedConstructor
106 };
107
108 // If Yes, the script inherits it's "this" environment and binding from the
109 // enclosing script. This is true for arrow-functions and eval scripts.
110 enum class InheritThis { No, Yes };
111
112 class GlobalSharedContext;
113 class EvalSharedContext;
114 class ModuleSharedContext;
115 class SuspendableContext;
116
117 #define IMMUTABLE_FLAG_GETTER_SETTER(lowerName, name) \
118 GENERIC_FLAG_GETTER_SETTER(ImmutableFlags, lowerName, name)
119
120 #define IMMUTABLE_FLAG_GETTER(lowerName, name) \
121 GENERIC_FLAG_GETTER(ImmutableFlags, lowerName, name)
122
123 /*
124 * The struct SharedContext is part of the current parser context (see
125 * ParseContext). It stores information that is reused between the parser and
126 * the bytecode emitter.
127 */
128 class SharedContext {
129 public:
130 JSContext* const cx_;
131
132 protected:
133 // See: BaseScript::immutableFlags_
134 ImmutableScriptFlags immutableFlags_ = {};
135
136 // The location of this script in the source. Note that the value here differs
137 // from the final BaseScript for the case of standalone functions.
138 // This field is copied to ScriptStencil, and shouldn't be modified after the
139 // copy.
140 SourceExtent extent_ = {};
141
142 protected:
143 // See: ThisBinding
144 ThisBinding thisBinding_ = ThisBinding::Global;
145
146 // These flags do not have corresponding script flags and may be inherited
147 // from the scope chain in the case of eval and arrows.
148 bool allowNewTarget_ : 1;
149 bool allowSuperProperty_ : 1;
150 bool allowSuperCall_ : 1;
151 bool allowArguments_ : 1;
152 bool inWith_ : 1;
153 bool inClass_ : 1;
154
155 // See `strict()` below.
156 bool localStrict : 1;
157
158 // True if "use strict"; appears in the body instead of being inherited.
159 bool hasExplicitUseStrict_ : 1;
160
161 // Tracks if script-related fields are already copied to ScriptStencilExtra.
162 //
163 // If this field is true, those fileds shouldn't be modified.
164 //
165 // For FunctionBox, some fields are allowed to be modified, but the
166 // modification should be synced with ScriptStencilExtra by
167 // FunctionBox::copyUpdated* methods.
168 bool isScriptExtraFieldCopiedToStencil : 1;
169
170 // End of fields.
171
172 enum class Kind : uint8_t { FunctionBox, Global, Eval, Module };
173
174 // Alias enum into SharedContext
175 using ImmutableFlags = ImmutableScriptFlagsEnum;
176
hasFlag(ImmutableFlags flag)177 [[nodiscard]] bool hasFlag(ImmutableFlags flag) const {
178 return immutableFlags_.hasFlag(flag);
179 }
180 void setFlag(ImmutableFlags flag, bool b = true) {
181 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
182 immutableFlags_.setFlag(flag, b);
183 }
clearFlag(ImmutableFlags flag)184 void clearFlag(ImmutableFlags flag) {
185 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
186 immutableFlags_.clearFlag(flag);
187 }
188
189 public:
190 SharedContext(JSContext* cx, Kind kind,
191 const JS::ReadOnlyCompileOptions& options,
192 Directives directives, SourceExtent extent);
193
IMMUTABLE_FLAG_GETTER_SETTER(isForEval,IsForEval)194 IMMUTABLE_FLAG_GETTER_SETTER(isForEval, IsForEval)
195 IMMUTABLE_FLAG_GETTER_SETTER(isModule, IsModule)
196 IMMUTABLE_FLAG_GETTER_SETTER(isFunction, IsFunction)
197 IMMUTABLE_FLAG_GETTER_SETTER(selfHosted, SelfHosted)
198 IMMUTABLE_FLAG_GETTER_SETTER(forceStrict, ForceStrict)
199 IMMUTABLE_FLAG_GETTER_SETTER(hasNonSyntacticScope, HasNonSyntacticScope)
200 IMMUTABLE_FLAG_GETTER_SETTER(noScriptRval, NoScriptRval)
201 IMMUTABLE_FLAG_GETTER(treatAsRunOnce, TreatAsRunOnce)
202 // Strict: custom logic below
203 IMMUTABLE_FLAG_GETTER_SETTER(hasModuleGoal, HasModuleGoal)
204 IMMUTABLE_FLAG_GETTER_SETTER(hasInnerFunctions, HasInnerFunctions)
205 IMMUTABLE_FLAG_GETTER_SETTER(hasDirectEval, HasDirectEval)
206 IMMUTABLE_FLAG_GETTER_SETTER(bindingsAccessedDynamically,
207 BindingsAccessedDynamically)
208 IMMUTABLE_FLAG_GETTER_SETTER(hasCallSiteObj, HasCallSiteObj)
209
210 const SourceExtent& extent() const { return extent_; }
211
isFunctionBox()212 bool isFunctionBox() const { return isFunction(); }
213 inline FunctionBox* asFunctionBox();
isModuleContext()214 bool isModuleContext() const { return isModule(); }
215 inline ModuleSharedContext* asModuleContext();
isSuspendableContext()216 bool isSuspendableContext() const { return isFunction() || isModule(); }
217 inline SuspendableContext* asSuspendableContext();
isGlobalContext()218 bool isGlobalContext() const {
219 return !(isFunction() || isModule() || isForEval());
220 }
221 inline GlobalSharedContext* asGlobalContext();
isEvalContext()222 bool isEvalContext() const { return isForEval(); }
223 inline EvalSharedContext* asEvalContext();
224
isTopLevelContext()225 bool isTopLevelContext() const { return !isFunction(); }
226
thisBinding()227 ThisBinding thisBinding() const { return thisBinding_; }
hasFunctionThisBinding()228 bool hasFunctionThisBinding() const {
229 return thisBinding() == ThisBinding::Function ||
230 thisBinding() == ThisBinding::DerivedConstructor;
231 }
needsThisTDZChecks()232 bool needsThisTDZChecks() const {
233 return thisBinding() == ThisBinding::DerivedConstructor;
234 }
235
isSelfHosted()236 bool isSelfHosted() const { return selfHosted(); }
allowNewTarget()237 bool allowNewTarget() const { return allowNewTarget_; }
allowSuperProperty()238 bool allowSuperProperty() const { return allowSuperProperty_; }
allowSuperCall()239 bool allowSuperCall() const { return allowSuperCall_; }
allowArguments()240 bool allowArguments() const { return allowArguments_; }
inWith()241 bool inWith() const { return inWith_; }
inClass()242 bool inClass() const { return inClass_; }
243
hasExplicitUseStrict()244 bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; }
setExplicitUseStrict()245 void setExplicitUseStrict() { hasExplicitUseStrict_ = true; }
246
immutableFlags()247 ImmutableScriptFlags immutableFlags() { return immutableFlags_; }
248
allBindingsClosedOver()249 bool allBindingsClosedOver() { return bindingsAccessedDynamically(); }
250
251 // The ImmutableFlag tracks if the entire script is strict, while the
252 // localStrict flag indicates the current region (such as class body) should
253 // be treated as strict. The localStrict flag will always be reset to false
254 // before the end of the script.
strict()255 bool strict() const { return hasFlag(ImmutableFlags::Strict) || localStrict; }
setStrictScript()256 void setStrictScript() { setFlag(ImmutableFlags::Strict); }
setLocalStrictMode(bool strict)257 bool setLocalStrictMode(bool strict) {
258 bool retVal = localStrict;
259 localStrict = strict;
260 return retVal;
261 }
262
263 void copyScriptExtraFields(ScriptStencilExtra& scriptExtra);
264 };
265
266 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
267 ScopeKind scopeKind_;
268
269 public:
270 GlobalScope::ParserData* bindings;
271
272 GlobalSharedContext(JSContext* cx, ScopeKind scopeKind,
273 const JS::ReadOnlyCompileOptions& options,
274 Directives directives, SourceExtent extent);
275
scopeKind()276 ScopeKind scopeKind() const { return scopeKind_; }
277 };
278
asGlobalContext()279 inline GlobalSharedContext* SharedContext::asGlobalContext() {
280 MOZ_ASSERT(isGlobalContext());
281 return static_cast<GlobalSharedContext*>(this);
282 }
283
284 class MOZ_STACK_CLASS EvalSharedContext : public SharedContext {
285 public:
286 EvalScope::ParserData* bindings;
287
288 EvalSharedContext(JSContext* cx, CompilationState& compilationState,
289 SourceExtent extent);
290 };
291
asEvalContext()292 inline EvalSharedContext* SharedContext::asEvalContext() {
293 MOZ_ASSERT(isEvalContext());
294 return static_cast<EvalSharedContext*>(this);
295 }
296
297 enum class HasHeritage { No, Yes };
298
299 class SuspendableContext : public SharedContext {
300 public:
301 SuspendableContext(JSContext* cx, Kind kind,
302 const JS::ReadOnlyCompileOptions& options,
303 Directives directives, SourceExtent extent,
304 bool isGenerator, bool isAsync);
305
IMMUTABLE_FLAG_GETTER_SETTER(isAsync,IsAsync)306 IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
307 IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
308
309 bool needsFinalYield() const { return isGenerator() || isAsync(); }
needsDotGeneratorName()310 bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
needsClearSlotsOnExit()311 bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); }
needsIteratorResult()312 bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
needsPromiseResult()313 bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
314 };
315
316 class FunctionBox : public SuspendableContext {
317 friend struct GCThingList;
318
319 CompilationState& compilationState_;
320
321 // If this FunctionBox refers to a lazy child of the function being
322 // compiled, this field holds the child's immediately enclosing scope's index.
323 // Once compilation succeeds, we will store the scope pointed by this in the
324 // child's BaseScript. (Debugger may become confused if lazy scripts refer to
325 // partially initialized enclosing scopes, so we must avoid storing the
326 // scope in the BaseScript until compilation has completed
327 // successfully.)
328 // This is copied to ScriptStencil.
329 // Any update after the copy should be synced to the ScriptStencil.
330 mozilla::Maybe<ScopeIndex> enclosingScopeIndex_;
331
332 // Names from the named lambda scope, if a named lambda.
333 LexicalScope::ParserData* namedLambdaBindings_ = nullptr;
334
335 // Names from the function scope.
336 FunctionScope::ParserData* functionScopeBindings_ = nullptr;
337
338 // Names from the extra 'var' scope of the function, if the parameter list
339 // has expressions.
340 VarScope::ParserData* extraVarScopeBindings_ = nullptr;
341
342 // The explicit or implicit name of the function. The FunctionFlags indicate
343 // the kind of name.
344 // This is copied to ScriptStencil.
345 // Any update after the copy should be synced to the ScriptStencil.
346 TaggedParserAtomIndex atom_;
347
348 // Index into CompilationStencil::scriptData.
349 ScriptIndex funcDataIndex_ = ScriptIndex(-1);
350
351 // See: FunctionFlags
352 // This is copied to ScriptStencil.
353 // Any update after the copy should be synced to the ScriptStencil.
354 FunctionFlags flags_ = {};
355
356 // See: ImmutableScriptData::funLength
357 uint16_t length_ = 0;
358
359 // JSFunction::nargs_
360 // This field is copied to ScriptStencil, and shouldn't be modified after the
361 // copy.
362 uint16_t nargs_ = 0;
363
364 // See: PrivateScriptData::memberInitializers_
365 // This field is copied to ScriptStencil, and shouldn't be modified after the
366 // copy.
367 MemberInitializers memberInitializers_ = MemberInitializers::Invalid();
368
369 public:
370 // Back pointer used by asm.js for error messages.
371 FunctionNode* functionNode = nullptr;
372
373 // True if bytecode will be emitted for this function in the current
374 // compilation.
375 bool emitBytecode : 1;
376
377 // This is set by the BytecodeEmitter of the enclosing script when a reference
378 // to this function is generated. This is also used to determine a hoisted
379 // function already is referenced by the bytecode.
380 bool wasEmittedByEnclosingScript_ : 1;
381
382 // Need to emit a synthesized Annex B assignment
383 bool isAnnexB : 1;
384
385 // Track if we saw "use asm".
386 // If we successfully validated it, `flags_` is seto to `AsmJS` kind.
387 bool useAsm : 1;
388
389 // Analysis of parameter list
390 bool hasParameterExprs : 1;
391 bool hasDestructuringArgs : 1;
392 bool hasDuplicateParameters : 1;
393
394 // Arrow function with expression body like: `() => 1`.
395 bool hasExprBody_ : 1;
396
397 // Used to issue an early error in static class blocks.
398 bool allowReturn_ : 1;
399
400 // Tracks if function-related fields are already copied to ScriptStencil.
401 // If this field is true, modification to those fields should be synced with
402 // ScriptStencil by copyUpdated* methods.
403 bool isFunctionFieldCopiedToStencil : 1;
404
405 // True if this is part of initial compilation.
406 // False if this is part of delazification.
407 bool isInitialCompilation : 1;
408
409 // True if this is standalone function
410 // (new Function() including generator/async, or event handler).
411 bool isStandalone : 1;
412
413 // End of fields.
414
415 FunctionBox(JSContext* cx, SourceExtent extent,
416 CompilationState& compilationState, Directives directives,
417 GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
418 bool isInitialCompilation, TaggedParserAtomIndex atom,
419 FunctionFlags flags, ScriptIndex index);
420
421 ScriptStencil& functionStencil() const;
422 ScriptStencilExtra& functionExtraStencil() const;
423
namedLambdaBindings()424 LexicalScope::ParserData* namedLambdaBindings() {
425 return namedLambdaBindings_;
426 }
setNamedLambdaBindings(LexicalScope::ParserData * bindings)427 void setNamedLambdaBindings(LexicalScope::ParserData* bindings) {
428 namedLambdaBindings_ = bindings;
429 }
430
functionScopeBindings()431 FunctionScope::ParserData* functionScopeBindings() {
432 return functionScopeBindings_;
433 }
setFunctionScopeBindings(FunctionScope::ParserData * bindings)434 void setFunctionScopeBindings(FunctionScope::ParserData* bindings) {
435 functionScopeBindings_ = bindings;
436 }
437
extraVarScopeBindings()438 VarScope::ParserData* extraVarScopeBindings() {
439 return extraVarScopeBindings_;
440 }
setExtraVarScopeBindings(VarScope::ParserData * bindings)441 void setExtraVarScopeBindings(VarScope::ParserData* bindings) {
442 extraVarScopeBindings_ = bindings;
443 }
444
445 void initFromLazyFunction(JSFunction* fun, ScopeContext& scopeContext,
446 FunctionFlags flags, FunctionSyntaxKind kind);
447 void initFromLazyFunctionToSkip(JSFunction* fun);
448 void initStandalone(ScopeContext& scopeContext, FunctionFlags flags,
449 FunctionSyntaxKind kind);
450
451 private:
452 void initFromLazyFunctionShared(JSFunction* fun);
453 void initStandaloneOrLazy(ScopeContext& scopeContext, FunctionFlags flags,
454 FunctionSyntaxKind kind);
455
456 public:
457 void initWithEnclosingParseContext(ParseContext* enclosing,
458 FunctionFlags flags,
459 FunctionSyntaxKind kind);
460
461 void setEnclosingScopeForInnerLazyFunction(ScopeIndex scopeIndex);
462
wasEmittedByEnclosingScript()463 bool wasEmittedByEnclosingScript() const {
464 return wasEmittedByEnclosingScript_;
465 }
setWasEmittedByEnclosingScript(bool wasEmitted)466 void setWasEmittedByEnclosingScript(bool wasEmitted) {
467 wasEmittedByEnclosingScript_ = wasEmitted;
468 if (isFunctionFieldCopiedToStencil) {
469 copyUpdatedWasEmitted();
470 }
471 }
472
473 [[nodiscard]] bool setAsmJSModule(const JS::WasmModule* module);
isAsmJSModule()474 bool isAsmJSModule() const { return flags_.isAsmJSNative(); }
475
hasEnclosingScopeIndex()476 bool hasEnclosingScopeIndex() const { return enclosingScopeIndex_.isSome(); }
getEnclosingScopeIndex()477 ScopeIndex getEnclosingScopeIndex() const { return *enclosingScopeIndex_; }
478
IMMUTABLE_FLAG_GETTER_SETTER(isAsync,IsAsync)479 IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
480 IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
481 IMMUTABLE_FLAG_GETTER_SETTER(funHasExtensibleScope, FunHasExtensibleScope)
482 IMMUTABLE_FLAG_GETTER_SETTER(functionHasThisBinding, FunctionHasThisBinding)
483 // NeedsHomeObject: custom logic below.
484 // IsDerivedClassConstructor: custom logic below.
485 // IsFieldInitializer: custom logic below.
486 IMMUTABLE_FLAG_GETTER(useMemberInitializers, UseMemberInitializers)
487 IMMUTABLE_FLAG_GETTER_SETTER(hasRest, HasRest)
488 IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects,
489 NeedsFunctionEnvironmentObjects)
490 IMMUTABLE_FLAG_GETTER_SETTER(functionHasExtraBodyVarScope,
491 FunctionHasExtraBodyVarScope)
492 IMMUTABLE_FLAG_GETTER_SETTER(shouldDeclareArguments, ShouldDeclareArguments)
493 IMMUTABLE_FLAG_GETTER_SETTER(needsArgsObj, NeedsArgsObj)
494 // HasMappedArgsObj: custom logic below.
495
496 bool needsCallObjectRegardlessOfBindings() const {
497 // Always create a CallObject if:
498 // - The scope is extensible at runtime due to sloppy eval.
499 // - The function is a generator or async function. (The debugger reads the
500 // generator object directly from the frame.)
501
502 return funHasExtensibleScope() || isGenerator() || isAsync();
503 }
504
needsExtraBodyVarEnvironmentRegardlessOfBindings()505 bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
506 MOZ_ASSERT(hasParameterExprs);
507 return funHasExtensibleScope();
508 }
509
generatorKind()510 GeneratorKind generatorKind() const {
511 return isGenerator() ? GeneratorKind::Generator
512 : GeneratorKind::NotGenerator;
513 }
514
asyncKind()515 FunctionAsyncKind asyncKind() const {
516 return isAsync() ? FunctionAsyncKind::AsyncFunction
517 : FunctionAsyncKind::SyncFunction;
518 }
519
needsFinalYield()520 bool needsFinalYield() const { return isGenerator() || isAsync(); }
needsDotGeneratorName()521 bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
needsClearSlotsOnExit()522 bool needsClearSlotsOnExit() const { return isGenerator() || isAsync(); }
needsIteratorResult()523 bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
needsPromiseResult()524 bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
525
isArrow()526 bool isArrow() const { return flags_.isArrow(); }
isLambda()527 bool isLambda() const { return flags_.isLambda(); }
528
hasExprBody()529 bool hasExprBody() const { return hasExprBody_; }
setHasExprBody()530 void setHasExprBody() {
531 MOZ_ASSERT(isArrow());
532 hasExprBody_ = true;
533 }
534
allowReturn()535 bool allowReturn() const { return allowReturn_; }
536
isNamedLambda()537 bool isNamedLambda() const { return flags_.isNamedLambda(!!explicitName()); }
isGetter()538 bool isGetter() const { return flags_.isGetter(); }
isSetter()539 bool isSetter() const { return flags_.isSetter(); }
isMethod()540 bool isMethod() const { return flags_.isMethod(); }
isClassConstructor()541 bool isClassConstructor() const { return flags_.isClassConstructor(); }
542
isInterpreted()543 bool isInterpreted() const { return flags_.hasBaseScript(); }
544
kind()545 FunctionFlags::FunctionKind kind() { return flags_.kind(); }
546
hasInferredName()547 bool hasInferredName() const { return flags_.hasInferredName(); }
hasGuessedAtom()548 bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
549
displayAtom()550 TaggedParserAtomIndex displayAtom() const { return atom_; }
explicitName()551 TaggedParserAtomIndex explicitName() const {
552 return (hasInferredName() || hasGuessedAtom())
553 ? TaggedParserAtomIndex::null()
554 : atom_;
555 }
556
557 // NOTE: We propagate to any existing functions for now. This handles both the
558 // delazification case where functions already exist, and also handles
559 // code-coverage which is not yet deferred.
setInferredName(TaggedParserAtomIndex atom)560 void setInferredName(TaggedParserAtomIndex atom) {
561 atom_ = atom;
562 flags_.setInferredName();
563 if (isFunctionFieldCopiedToStencil) {
564 copyUpdatedAtomAndFlags();
565 }
566 }
setGuessedAtom(TaggedParserAtomIndex atom)567 void setGuessedAtom(TaggedParserAtomIndex atom) {
568 atom_ = atom;
569 flags_.setGuessedAtom();
570 if (isFunctionFieldCopiedToStencil) {
571 copyUpdatedAtomAndFlags();
572 }
573 }
574
needsHomeObject()575 bool needsHomeObject() const {
576 return hasFlag(ImmutableFlags::NeedsHomeObject);
577 }
setNeedsHomeObject()578 void setNeedsHomeObject() {
579 MOZ_ASSERT(flags_.allowSuperProperty());
580 setFlag(ImmutableFlags::NeedsHomeObject);
581 }
582
isDerivedClassConstructor()583 bool isDerivedClassConstructor() const {
584 return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
585 }
setDerivedClassConstructor()586 void setDerivedClassConstructor() {
587 MOZ_ASSERT(flags_.isClassConstructor());
588 setFlag(ImmutableFlags::IsDerivedClassConstructor);
589 }
590
isSyntheticFunction()591 bool isSyntheticFunction() const {
592 return hasFlag(ImmutableFlags::IsSyntheticFunction);
593 }
setSyntheticFunction()594 void setSyntheticFunction() {
595 // Field initializer or class consturctor.
596 MOZ_ASSERT(flags_.isMethod());
597 setFlag(ImmutableFlags::IsSyntheticFunction);
598 }
599
hasSimpleParameterList()600 bool hasSimpleParameterList() const {
601 return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
602 }
603
hasMappedArgsObj()604 bool hasMappedArgsObj() const {
605 return !strict() && hasSimpleParameterList();
606 }
607
608 // Return whether this or an enclosing function is being parsed and
609 // validated as asm.js. Note: if asm.js validation fails, this will be false
610 // while the function is being reparsed. This flag can be used to disable
611 // certain parsing features that are necessary in general, but unnecessary
612 // for validated asm.js.
useAsmOrInsideUseAsm()613 bool useAsmOrInsideUseAsm() const { return useAsm; }
614
setStart(uint32_t offset,uint32_t line,uint32_t column)615 void setStart(uint32_t offset, uint32_t line, uint32_t column) {
616 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
617 extent_.sourceStart = offset;
618 extent_.lineno = line;
619 extent_.column = column;
620 }
621
setEnd(uint32_t end)622 void setEnd(uint32_t end) {
623 MOZ_ASSERT(!isScriptExtraFieldCopiedToStencil);
624 // For all functions except class constructors, the buffer and
625 // toString ending positions are the same. Class constructors override
626 // the toString ending position with the end of the class definition.
627 extent_.sourceEnd = end;
628 extent_.toStringEnd = end;
629 }
630
setCtorToStringEnd(uint32_t end)631 void setCtorToStringEnd(uint32_t end) {
632 extent_.toStringEnd = end;
633 if (isScriptExtraFieldCopiedToStencil) {
634 copyUpdatedExtent();
635 }
636 }
637
setCtorFunctionHasThisBinding()638 void setCtorFunctionHasThisBinding() {
639 immutableFlags_.setFlag(ImmutableFlags::FunctionHasThisBinding, true);
640 if (isScriptExtraFieldCopiedToStencil) {
641 copyUpdatedImmutableFlags();
642 }
643 }
644
setIsInlinableLargeFunction()645 void setIsInlinableLargeFunction() {
646 immutableFlags_.setFlag(ImmutableFlags::IsInlinableLargeFunction, true);
647 if (isScriptExtraFieldCopiedToStencil) {
648 copyUpdatedImmutableFlags();
649 }
650 }
651
length()652 uint16_t length() { return length_; }
setLength(uint16_t length)653 void setLength(uint16_t length) { length_ = length; }
654
setArgCount(uint16_t args)655 void setArgCount(uint16_t args) {
656 MOZ_ASSERT(!isFunctionFieldCopiedToStencil);
657 nargs_ = args;
658 }
659
nargs()660 size_t nargs() { return nargs_; }
661
memberInitializers()662 const MemberInitializers& memberInitializers() const {
663 MOZ_ASSERT(useMemberInitializers());
664 return memberInitializers_;
665 }
setMemberInitializers(MemberInitializers memberInitializers)666 void setMemberInitializers(MemberInitializers memberInitializers) {
667 immutableFlags_.setFlag(ImmutableFlags::UseMemberInitializers, true);
668 memberInitializers_ = memberInitializers;
669 if (isScriptExtraFieldCopiedToStencil) {
670 copyUpdatedImmutableFlags();
671 copyUpdatedMemberInitializers();
672 }
673 }
674
index()675 ScriptIndex index() { return funcDataIndex_; }
676
677 void finishScriptFlags();
678 void copyFunctionFields(ScriptStencil& script);
679 void copyFunctionExtraFields(ScriptStencilExtra& scriptExtra);
680
681 // * setCtorFunctionHasThisBinding can be called to a class constructor
682 // with a lazy function, while parsing enclosing class
683 // * setIsInlinableLargeFunction can be called by BCE to update flags of the
684 // previous top-level function, but only in self-hosted mode.
685 void copyUpdatedImmutableFlags();
686
687 // * setCtorToStringEnd bcan be called to a class constructor with a lazy
688 // function, while parsing enclosing class
689 void copyUpdatedExtent();
690
691 // * setMemberInitializers can be called to a class constructor with a lazy
692 // function, while emitting enclosing script
693 void copyUpdatedMemberInitializers();
694
695 // * setEnclosingScopeForInnerLazyFunction can be called to a lazy function,
696 // while emitting enclosing script
697 void copyUpdatedEnclosingScopeIndex();
698
699 // * setInferredName can be called to a lazy function, while emitting
700 // enclosing script
701 // * setGuessedAtom can be called to both lazy/non-lazy functions,
702 // while running NameFunctions
703 void copyUpdatedAtomAndFlags();
704
705 // * setWasEmitted can be called to a lazy function, while emitting
706 // enclosing script
707 void copyUpdatedWasEmitted();
708 };
709
710 #undef FLAG_GETTER_SETTER
711 #undef IMMUTABLE_FLAG_GETTER_SETTER
712
asFunctionBox()713 inline FunctionBox* SharedContext::asFunctionBox() {
714 MOZ_ASSERT(isFunctionBox());
715 return static_cast<FunctionBox*>(this);
716 }
717
asSuspendableContext()718 inline SuspendableContext* SharedContext::asSuspendableContext() {
719 MOZ_ASSERT(isSuspendableContext());
720 return static_cast<SuspendableContext*>(this);
721 }
722
723 } // namespace frontend
724 } // namespace js
725
726 #endif /* frontend_SharedContext_h */
727