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