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"
17 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
18 #include "frontend/ParseNode.h"
19 #include "frontend/Stencil.h"
20 #include "vm/FunctionFlags.h"          // js::FunctionFlags
21 #include "vm/GeneratorAndAsyncKind.h"  // js::GeneratorKind, js::FunctionAsyncKind
22 #include "vm/JSFunction.h"
23 #include "vm/JSScript.h"
24 #include "vm/Scope.h"
25 #include "vm/SharedStencil.h"
26 
27 namespace js {
28 namespace frontend {
29 
30 class ParseContext;
31 struct ScopeContext;
32 
33 enum class StatementKind : uint8_t {
34   Label,
35   Block,
36   If,
37   Switch,
38   With,
39   Catch,
40   Try,
41   Finally,
42   ForLoopLexicalHead,
43   ForLoop,
44   ForInLoop,
45   ForOfLoop,
46   DoLoop,
47   WhileLoop,
48   Class,
49 
50   // Used only by BytecodeEmitter.
51   Spread,
52   YieldStar,
53 };
54 
StatementKindIsLoop(StatementKind kind)55 static inline bool StatementKindIsLoop(StatementKind kind) {
56   return kind == StatementKind::ForLoop || kind == StatementKind::ForInLoop ||
57          kind == StatementKind::ForOfLoop || kind == StatementKind::DoLoop ||
58          kind == StatementKind::WhileLoop || kind == StatementKind::Spread ||
59          kind == StatementKind::YieldStar;
60 }
61 
StatementKindIsUnlabeledBreakTarget(StatementKind kind)62 static inline bool StatementKindIsUnlabeledBreakTarget(StatementKind kind) {
63   return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
64 }
65 
66 // List of directives that may be encountered in a Directive Prologue
67 // (ES5 15.1).
68 class Directives {
69   bool strict_;
70   bool asmJS_;
71 
72  public:
Directives(bool strict)73   explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
74   explicit Directives(ParseContext* parent);
75 
setStrict()76   void setStrict() { strict_ = true; }
strict()77   bool strict() const { return strict_; }
78 
setAsmJS()79   void setAsmJS() { asmJS_ = true; }
asmJS()80   bool asmJS() const { return asmJS_; }
81 
82   Directives& operator=(Directives rhs) {
83     strict_ = rhs.strict_;
84     asmJS_ = rhs.asmJS_;
85     return *this;
86   }
87   bool operator==(const Directives& rhs) const {
88     return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
89   }
90   bool operator!=(const Directives& rhs) const { return !(*this == rhs); }
91 };
92 
93 // The kind of this-binding for the current scope. Note that arrow functions
94 // have a lexical this-binding so their ThisBinding is the same as the
95 // ThisBinding of their enclosing scope and can be any value. Derived
96 // constructors require TDZ checks when accessing the binding.
97 enum class ThisBinding : uint8_t {
98   Global,
99   Module,
100   Function,
101   DerivedConstructor
102 };
103 
104 class GlobalSharedContext;
105 class EvalSharedContext;
106 class ModuleSharedContext;
107 
108 #define FLAG_GETTER_SETTER(enumName, enumEntry, lowerName, name)  \
109  public:                                                          \
110   bool lowerName() const { return hasFlag(enumName::enumEntry); } \
111   void set##name() { setFlag(enumName::enumEntry); }              \
112   void set##name(bool b) { setFlag(enumName::enumEntry, b); }
113 
114 #define IMMUTABLE_FLAG_GETTER_SETTER(lowerName, name) \
115   FLAG_GETTER_SETTER(ImmutableFlags, name, lowerName, name)
116 
117 /*
118  * The struct SharedContext is part of the current parser context (see
119  * ParseContext). It stores information that is reused between the parser and
120  * the bytecode emitter.
121  */
122 class SharedContext {
123  public:
124   JSContext* const cx_;
125 
126  protected:
127   CompilationInfo& compilationInfo_;
128 
129   // See: BaseScript::immutableFlags_
130   ImmutableScriptFlags immutableFlags_ = {};
131 
132  public:
133   // The location of this script in the source. Note that the value here differs
134   // from the final BaseScript for the case of standalone functions.
135   SourceExtent extent = {};
136 
137  protected:
138   // See: ThisBinding
139   ThisBinding thisBinding_ = ThisBinding::Global;
140 
141   // These flags do not have corresponding script flags and may be inherited
142   // from the scope chain in the case of eval and arrows.
143   bool allowNewTarget_ : 1;
144   bool allowSuperProperty_ : 1;
145   bool allowSuperCall_ : 1;
146   bool allowArguments_ : 1;
147   bool inWith_ : 1;
148 
149   // See `strict()` below.
150   bool localStrict : 1;
151 
152   // True if "use strict"; appears in the body instead of being inherited.
153   bool hasExplicitUseStrict_ : 1;
154 
155   // End of fields.
156 
157   enum class Kind : uint8_t { FunctionBox, Global, Eval, Module };
158 
159   // Alias enum into SharedContext
160   using ImmutableFlags = ImmutableScriptFlagsEnum;
161 
hasFlag(ImmutableFlags flag)162   MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const {
163     return immutableFlags_.hasFlag(flag);
164   }
165   void setFlag(ImmutableFlags flag, bool b = true) {
166     immutableFlags_.setFlag(flag, b);
167   }
168 
169  public:
170   SharedContext(JSContext* cx, Kind kind, CompilationInfo& compilationInfo,
171                 Directives directives, SourceExtent extent);
172 
173   // If this is the outermost SharedContext, the Scope that encloses
174   // it. Otherwise nullptr.
175   virtual Scope* compilationEnclosingScope() const = 0;
176 
IMMUTABLE_FLAG_GETTER_SETTER(isForEval,IsForEval)177   IMMUTABLE_FLAG_GETTER_SETTER(isForEval, IsForEval)
178   IMMUTABLE_FLAG_GETTER_SETTER(isModule, IsModule)
179   IMMUTABLE_FLAG_GETTER_SETTER(isFunction, IsFunction)
180   IMMUTABLE_FLAG_GETTER_SETTER(selfHosted, SelfHosted)
181   IMMUTABLE_FLAG_GETTER_SETTER(forceStrict, ForceStrict)
182   IMMUTABLE_FLAG_GETTER_SETTER(hasNonSyntacticScope, HasNonSyntacticScope)
183   IMMUTABLE_FLAG_GETTER_SETTER(noScriptRval, NoScriptRval)
184   IMMUTABLE_FLAG_GETTER_SETTER(treatAsRunOnce, TreatAsRunOnce)
185   // Strict: custom logic below
186   IMMUTABLE_FLAG_GETTER_SETTER(hasModuleGoal, HasModuleGoal)
187   IMMUTABLE_FLAG_GETTER_SETTER(hasInnerFunctions, HasInnerFunctions)
188   IMMUTABLE_FLAG_GETTER_SETTER(hasDirectEval, HasDirectEval)
189   IMMUTABLE_FLAG_GETTER_SETTER(bindingsAccessedDynamically,
190                                BindingsAccessedDynamically)
191   IMMUTABLE_FLAG_GETTER_SETTER(hasCallSiteObj, HasCallSiteObj)
192 
193   bool isFunctionBox() const { return isFunction(); }
194   inline FunctionBox* asFunctionBox();
isModuleContext()195   bool isModuleContext() const { return isModule(); }
196   inline ModuleSharedContext* asModuleContext();
isGlobalContext()197   bool isGlobalContext() const {
198     return !(isFunction() || isModule() || isForEval());
199   }
200   inline GlobalSharedContext* asGlobalContext();
isEvalContext()201   bool isEvalContext() const { return isForEval(); }
202   inline EvalSharedContext* asEvalContext();
203 
isTopLevelContext()204   bool isTopLevelContext() const { return !isFunction(); }
205 
compilationInfo()206   CompilationInfo& compilationInfo() const { return compilationInfo_; }
207 
thisBinding()208   ThisBinding thisBinding() const { return thisBinding_; }
hasFunctionThisBinding()209   bool hasFunctionThisBinding() const {
210     return thisBinding() == ThisBinding::Function ||
211            thisBinding() == ThisBinding::DerivedConstructor;
212   }
needsThisTDZChecks()213   bool needsThisTDZChecks() const {
214     return thisBinding() == ThisBinding::DerivedConstructor;
215   }
216 
isSelfHosted()217   bool isSelfHosted() const { return selfHosted(); }
allowNewTarget()218   bool allowNewTarget() const { return allowNewTarget_; }
allowSuperProperty()219   bool allowSuperProperty() const { return allowSuperProperty_; }
allowSuperCall()220   bool allowSuperCall() const { return allowSuperCall_; }
allowArguments()221   bool allowArguments() const { return allowArguments_; }
inWith()222   bool inWith() const { return inWith_; }
223 
hasExplicitUseStrict()224   bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; }
setExplicitUseStrict()225   void setExplicitUseStrict() { hasExplicitUseStrict_ = true; }
226 
immutableFlags()227   ImmutableScriptFlags immutableFlags() { return immutableFlags_; }
228 
229   inline bool allBindingsClosedOver();
230 
231   // The ImmutableFlag tracks if the entire script is strict, while the
232   // localStrict flag indicates the current region (such as class body) should
233   // be treated as strict. The localStrict flag will always be reset to false
234   // before the end of the script.
strict()235   bool strict() const { return hasFlag(ImmutableFlags::Strict) || localStrict; }
setStrictScript()236   void setStrictScript() { setFlag(ImmutableFlags::Strict); }
setLocalStrictMode(bool strict)237   bool setLocalStrictMode(bool strict) {
238     bool retVal = localStrict;
239     localStrict = strict;
240     return retVal;
241   }
242 };
243 
244 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
245   ScopeKind scopeKind_;
246 
247  public:
248   Rooted<GlobalScope::Data*> bindings;
249 
GlobalSharedContext(JSContext * cx,ScopeKind scopeKind,CompilationInfo & compilationInfo,Directives directives,SourceExtent extent)250   GlobalSharedContext(JSContext* cx, ScopeKind scopeKind,
251                       CompilationInfo& compilationInfo, Directives directives,
252                       SourceExtent extent)
253       : SharedContext(cx, Kind::Global, compilationInfo, directives, extent),
254         scopeKind_(scopeKind),
255         bindings(cx) {
256     MOZ_ASSERT(scopeKind == ScopeKind::Global ||
257                scopeKind == ScopeKind::NonSyntactic);
258     MOZ_ASSERT(thisBinding_ == ThisBinding::Global);
259   }
260 
compilationEnclosingScope()261   Scope* compilationEnclosingScope() const override { return nullptr; }
262 
scopeKind()263   ScopeKind scopeKind() const { return scopeKind_; }
264 };
265 
asGlobalContext()266 inline GlobalSharedContext* SharedContext::asGlobalContext() {
267   MOZ_ASSERT(isGlobalContext());
268   return static_cast<GlobalSharedContext*>(this);
269 }
270 
271 class MOZ_STACK_CLASS EvalSharedContext : public SharedContext {
272   RootedScope enclosingScope_;
273 
274  public:
275   Rooted<EvalScope::Data*> bindings;
276 
277   EvalSharedContext(JSContext* cx, CompilationInfo& compilationInfo,
278                     Scope* enclosingScope, Directives directives,
279                     SourceExtent extent);
280 
compilationEnclosingScope()281   Scope* compilationEnclosingScope() const override { return enclosingScope_; }
282 };
283 
asEvalContext()284 inline EvalSharedContext* SharedContext::asEvalContext() {
285   MOZ_ASSERT(isEvalContext());
286   return static_cast<EvalSharedContext*>(this);
287 }
288 
289 enum class HasHeritage { No, Yes };
290 enum class TopLevelFunction { No, Yes };
291 
292 class FunctionBox : public SharedContext {
293   friend struct GCThingList;
294 
295   // The parser handles tracing the fields below via the FunctionBox linked
296   // list represented by |traceLink_|.
297   FunctionBox* traceLink_ = nullptr;
298 
299   // This field is used for two purposes:
300   //   * If this FunctionBox refers to the function being compiled, this field
301   //     holds its enclosing scope, used for compilation.
302   //   * If this FunctionBox refers to a lazy child of the function being
303   //     compiled, this field holds the child's immediately enclosing scope.
304   //     Once compilation succeeds, we will store it in the child's
305   //     BaseScript.  (Debugger may become confused if lazy scripts refer to
306   //     partially initialized enclosing scopes, so we must avoid storing the
307   //     scope in the BaseScript until compilation has completed
308   //     successfully.)
309   AbstractScopePtr enclosingScope_ = {};
310 
311   // Names from the named lambda scope, if a named lambda.
312   LexicalScope::Data* namedLambdaBindings_ = nullptr;
313 
314   // Names from the function scope.
315   FunctionScope::Data* functionScopeBindings_ = nullptr;
316 
317   // Names from the extra 'var' scope of the function, if the parameter list
318   // has expressions.
319   VarScope::Data* extraVarScopeBindings_ = nullptr;
320 
321   // The explicit or implicit name of the function. The FunctionFlags indicate
322   // the kind of name.
323   JSAtom* atom_ = nullptr;
324 
325   // Index into CompilationInfo::funcData, which contains the function
326   // information, either a JSFunction* (for a FunctionBox representing a real
327   // function) or a ScriptStencilBase.
328   size_t funcDataIndex_ = (size_t)(-1);
329 
330  public:
331   // Back pointer used by asm.js for error messages.
332   FunctionNode* functionNode = nullptr;
333 
334   // See: PrivateScriptData::fieldInitializers_
335   mozilla::Maybe<FieldInitializers> fieldInitializers = {};
336 
337   FunctionFlags flags_ = {};  // See: FunctionFlags
338   uint16_t length = 0;        // See: ImmutableScriptData::funLength
339   uint16_t nargs_ = 0;        // JSFunction::nargs_
340 
341   // True if bytecode will be emitted for this function in the current
342   // compilation.
343   bool emitBytecode : 1;
344 
345   // This is set by the BytecodeEmitter of the enclosing script when a reference
346   // to this function is generated. This is also used to determine a hoisted
347   // function already is referenced by the bytecode.
348   bool wasEmitted : 1;
349 
350   // This function should be marked as a singleton. It is expected to be defined
351   // at most once. This is a heuristic only and does not affect correctness.
352   bool isSingleton : 1;
353 
354   // Need to emit a synthesized Annex B assignment
355   bool isAnnexB : 1;
356 
357   // Track if we saw "use asm" and if we successfully validated.
358   bool useAsm : 1;
359   bool isAsmJSModule_ : 1;
360 
361   // Analysis of parameter list
362   bool hasParameterExprs : 1;
363   bool hasDestructuringArgs : 1;
364   bool hasDuplicateParameters : 1;
365 
366   // Arrow function with expression body like: `() => 1`.
367   bool hasExprBody_ : 1;
368 
369   // Analysis for use in heuristics.
370   bool usesApply : 1;   // Contains an f.apply() call
371   bool usesThis : 1;    // Contains 'this'
372   bool usesReturn : 1;  // Contains a 'return' statement
373 
374   // End of fields.
375 
376   FunctionBox(JSContext* cx, FunctionBox* traceListHead, SourceExtent extent,
377               CompilationInfo& compilationInfo, Directives directives,
378               GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
379               JSAtom* explicitName, FunctionFlags flags, size_t index);
380 
381   JSFunction* createFunction(JSContext* cx);
382 
383   MutableHandle<ScriptStencil> functionStencil() const;
384 
385   bool hasFunctionStencil() const;
386   bool hasFunction() const;
387 
388 #ifdef DEBUG
389   bool atomsAreKept();
390 #endif
391 
namedLambdaBindings()392   MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
393     MOZ_ASSERT(atomsAreKept());
394     return MutableHandle<LexicalScope::Data*>::fromMarkedLocation(
395         &namedLambdaBindings_);
396   }
397 
functionScopeBindings()398   MutableHandle<FunctionScope::Data*> functionScopeBindings() {
399     MOZ_ASSERT(atomsAreKept());
400     return MutableHandle<FunctionScope::Data*>::fromMarkedLocation(
401         &functionScopeBindings_);
402   }
403 
extraVarScopeBindings()404   MutableHandle<VarScope::Data*> extraVarScopeBindings() {
405     MOZ_ASSERT(atomsAreKept());
406     return MutableHandle<VarScope::Data*>::fromMarkedLocation(
407         &extraVarScopeBindings_);
408   }
409 
410   void initFromLazyFunction(JSFunction* fun);
411 
412   void initWithEnclosingScope(ScopeContext& scopeContext, Scope* enclosingScope,
413                               FunctionFlags flags, FunctionSyntaxKind kind);
414 
415   void initWithEnclosingParseContext(ParseContext* enclosing,
416                                      FunctionFlags flags,
417                                      FunctionSyntaxKind kind);
418 
419   void setEnclosingScopeForInnerLazyFunction(
420       const AbstractScopePtr& enclosingScope);
421   void finish();
422 
423   JSFunction* function() const;
424 
425   // Initialize FunctionBox with a deferred allocation Function
initializeFunction(JSFunction * fun)426   void initializeFunction(JSFunction* fun) { clobberFunction(fun); }
427 
428   void setAsmJSModule(JSFunction* function);
isAsmJSModule()429   bool isAsmJSModule() { return isAsmJSModule_; }
430 
431   void clobberFunction(JSFunction* function);
432 
compilationEnclosingScope()433   Scope* compilationEnclosingScope() const override {
434     // This is used when emitting code for the current FunctionBox and therefore
435     // the enclosingScope_ must have be set correctly during initalization.
436 
437     MOZ_ASSERT(enclosingScope_);
438     return enclosingScope_.scope();
439   }
440 
IMMUTABLE_FLAG_GETTER_SETTER(isAsync,IsAsync)441   IMMUTABLE_FLAG_GETTER_SETTER(isAsync, IsAsync)
442   IMMUTABLE_FLAG_GETTER_SETTER(isGenerator, IsGenerator)
443   IMMUTABLE_FLAG_GETTER_SETTER(funHasExtensibleScope, FunHasExtensibleScope)
444   IMMUTABLE_FLAG_GETTER_SETTER(functionHasThisBinding, FunctionHasThisBinding)
445   // NeedsHomeObject: custom logic below.
446   // IsDerivedClassConstructor: custom logic below.
447   // IsFieldInitializer: custom logic below.
448   IMMUTABLE_FLAG_GETTER_SETTER(hasRest, HasRest)
449   IMMUTABLE_FLAG_GETTER_SETTER(needsFunctionEnvironmentObjects,
450                                NeedsFunctionEnvironmentObjects)
451   IMMUTABLE_FLAG_GETTER_SETTER(functionHasExtraBodyVarScope,
452                                FunctionHasExtraBodyVarScope)
453   IMMUTABLE_FLAG_GETTER_SETTER(shouldDeclareArguments, ShouldDeclareArguments)
454   IMMUTABLE_FLAG_GETTER_SETTER(argumentsHasVarBinding, ArgumentsHasVarBinding)
455   // AlwaysNeedsArgsObj: custom logic below.
456   // HasMappedArgsObj: custom logic below.
457   // IsLikelyConstructorWrapper: custom logic below.
458 
459   bool needsCallObjectRegardlessOfBindings() const {
460     // Always create a CallObject if:
461     // - The scope is extensible at runtime due to sloppy eval.
462     // - The function is a generator or async function. (The debugger reads the
463     //   generator object directly from the frame.)
464 
465     return funHasExtensibleScope() || isGenerator() || isAsync();
466   }
467 
needsExtraBodyVarEnvironmentRegardlessOfBindings()468   bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
469     MOZ_ASSERT(hasParameterExprs);
470     return funHasExtensibleScope();
471   }
472 
isLikelyConstructorWrapper()473   bool isLikelyConstructorWrapper() const {
474     return argumentsHasVarBinding() && usesApply && usesThis && !usesReturn;
475   }
476 
generatorKind()477   GeneratorKind generatorKind() const {
478     return isGenerator() ? GeneratorKind::Generator
479                          : GeneratorKind::NotGenerator;
480   }
481 
asyncKind()482   FunctionAsyncKind asyncKind() const {
483     return isAsync() ? FunctionAsyncKind::AsyncFunction
484                      : FunctionAsyncKind::SyncFunction;
485   }
486 
needsFinalYield()487   bool needsFinalYield() const { return isGenerator() || isAsync(); }
needsDotGeneratorName()488   bool needsDotGeneratorName() const { return isGenerator() || isAsync(); }
needsIteratorResult()489   bool needsIteratorResult() const { return isGenerator() && !isAsync(); }
needsPromiseResult()490   bool needsPromiseResult() const { return isAsync() && !isGenerator(); }
491 
isArrow()492   bool isArrow() const { return flags_.isArrow(); }
isLambda()493   bool isLambda() const { return flags_.isLambda(); }
494 
hasExprBody()495   bool hasExprBody() const { return hasExprBody_; }
setHasExprBody()496   void setHasExprBody() {
497     MOZ_ASSERT(isArrow());
498     hasExprBody_ = true;
499   }
500 
isNamedLambda()501   bool isNamedLambda() const {
502     return flags_.isNamedLambda(explicitName() != nullptr);
503   }
isGetter()504   bool isGetter() const { return flags_.isGetter(); }
isSetter()505   bool isSetter() const { return flags_.isSetter(); }
isMethod()506   bool isMethod() const { return flags_.isMethod(); }
isClassConstructor()507   bool isClassConstructor() const { return flags_.isClassConstructor(); }
508 
isInterpreted()509   bool isInterpreted() const { return flags_.hasBaseScript(); }
setIsInterpreted(bool interpreted)510   void setIsInterpreted(bool interpreted) {
511     flags_.setFlags(FunctionFlags::BASESCRIPT, interpreted);
512   }
513 
kind()514   FunctionFlags::FunctionKind kind() { return flags_.kind(); }
515 
hasInferredName()516   bool hasInferredName() const { return flags_.hasInferredName(); }
hasGuessedAtom()517   bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
518 
displayAtom()519   JSAtom* displayAtom() const { return atom_; }
explicitName()520   JSAtom* explicitName() const {
521     return (hasInferredName() || hasGuessedAtom()) ? nullptr : atom_;
522   }
523 
524   // NOTE: We propagate to any existing functions for now. This handles both the
525   // delazification case where functions already exist, and also handles
526   // code-coverage which is not yet deferred.
setInferredName(JSAtom * atom)527   void setInferredName(JSAtom* atom) {
528     atom_ = atom;
529     flags_.setInferredName();
530   }
setGuessedAtom(JSAtom * atom)531   void setGuessedAtom(JSAtom* atom) {
532     atom_ = atom;
533     flags_.setGuessedAtom();
534   }
535 
setAlwaysNeedsArgsObj()536   void setAlwaysNeedsArgsObj() {
537     MOZ_ASSERT(argumentsHasVarBinding());
538     setFlag(ImmutableFlags::AlwaysNeedsArgsObj);
539   }
540 
needsHomeObject()541   bool needsHomeObject() const {
542     return hasFlag(ImmutableFlags::NeedsHomeObject);
543   }
setNeedsHomeObject()544   void setNeedsHomeObject() {
545     MOZ_ASSERT(flags_.allowSuperProperty());
546     setFlag(ImmutableFlags::NeedsHomeObject);
547   }
548 
isDerivedClassConstructor()549   bool isDerivedClassConstructor() const {
550     return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
551   }
setDerivedClassConstructor()552   void setDerivedClassConstructor() {
553     MOZ_ASSERT(flags_.isClassConstructor());
554     setFlag(ImmutableFlags::IsDerivedClassConstructor);
555   }
556 
isFieldInitializer()557   bool isFieldInitializer() const {
558     return hasFlag(ImmutableFlags::IsFieldInitializer);
559   }
setFieldInitializer()560   void setFieldInitializer() {
561     MOZ_ASSERT(flags_.isMethod());
562     setFlag(ImmutableFlags::IsFieldInitializer);
563   }
564 
hasSimpleParameterList()565   bool hasSimpleParameterList() const {
566     return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
567   }
568 
hasMappedArgsObj()569   bool hasMappedArgsObj() const {
570     return !strict() && hasSimpleParameterList();
571   }
572 
shouldSuppressRunOnce()573   bool shouldSuppressRunOnce() const {
574     // These heuristics suppress the run-once optimization if we expect that
575     // script-cloning will have more impact than TI type-precision would gain.
576     //
577     // See also: Bug 864218
578     return explicitName() || argumentsHasVarBinding() || isGenerator() ||
579            isAsync();
580   }
581 
582   // Return whether this or an enclosing function is being parsed and
583   // validated as asm.js. Note: if asm.js validation fails, this will be false
584   // while the function is being reparsed. This flag can be used to disable
585   // certain parsing features that are necessary in general, but unnecessary
586   // for validated asm.js.
useAsmOrInsideUseAsm()587   bool useAsmOrInsideUseAsm() const { return useAsm; }
588 
setStart(uint32_t offset,uint32_t line,uint32_t column)589   void setStart(uint32_t offset, uint32_t line, uint32_t column) {
590     extent.sourceStart = offset;
591     extent.lineno = line;
592     extent.column = column;
593   }
594 
setEnd(uint32_t end)595   void setEnd(uint32_t end) {
596     // For all functions except class constructors, the buffer and
597     // toString ending positions are the same. Class constructors override
598     // the toString ending position with the end of the class definition.
599     extent.sourceEnd = end;
600     extent.toStringEnd = end;
601   }
602 
setArgCount(uint16_t args)603   void setArgCount(uint16_t args) { nargs_ = args; }
604 
nargs()605   size_t nargs() { return nargs_; }
606 
607   // Flush the acquired argCount to the associated function.
synchronizeArgCount()608   void synchronizeArgCount() { function()->setArgCount(nargs_); }
609 
setTypeForScriptedFunction(JSContext * cx)610   bool setTypeForScriptedFunction(JSContext* cx) {
611     RootedFunction fun(cx, function());
612     return JSFunction::setTypeForScriptedFunction(cx, fun, isSingleton);
613   }
614 
index()615   size_t index() { return funcDataIndex_; }
616 
617   void trace(JSTracer* trc);
618 
619   static void TraceList(JSTracer* trc, FunctionBox* listHead);
620 
traceLink()621   FunctionBox* traceLink() { return traceLink_; }
622 };
623 
624 #undef FLAG_GETTER_SETTER
625 #undef IMMUTABLE_FLAG_GETTER_SETTER
626 
asFunctionBox()627 inline FunctionBox* SharedContext::asFunctionBox() {
628   MOZ_ASSERT(isFunctionBox());
629   return static_cast<FunctionBox*>(this);
630 }
631 
632 // In generators, we treat all bindings as closed so that they get stored on
633 // the heap.  This way there is less information to copy off the stack when
634 // suspending, and back on when resuming.  It also avoids the need to create
635 // and invalidate DebugScope proxies for unaliased locals in a generator
636 // frame, as the generator frame will be copied out to the heap and released
637 // only by GC.
allBindingsClosedOver()638 inline bool SharedContext::allBindingsClosedOver() {
639   return bindingsAccessedDynamically() ||
640          (isFunctionBox() &&
641           (asFunctionBox()->isGenerator() || asFunctionBox()->isAsync()));
642 }
643 
644 }  // namespace frontend
645 }  // namespace js
646 
647 #endif /* frontend_SharedContext_h */
648