LCOV - code coverage report
Current view: top level - js/src/frontend - SharedContext.h (source / functions) Hit Total Coverage
Test: output.info Lines: 165 186 88.7 %
Date: 2017-07-14 16:53:18 Functions: 77 89 86.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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 "jsatom.h"
      11             : #include "jsopcode.h"
      12             : #include "jspubtd.h"
      13             : #include "jsscript.h"
      14             : #include "jstypes.h"
      15             : 
      16             : #include "builtin/ModuleObject.h"
      17             : #include "ds/InlineTable.h"
      18             : #include "frontend/TokenStream.h"
      19             : #include "vm/EnvironmentObject.h"
      20             : 
      21             : namespace js {
      22             : namespace frontend {
      23             : 
      24             : class ParseNode;
      25             : 
      26             : enum class StatementKind : uint8_t
      27             : {
      28             :     Label,
      29             :     Block,
      30             :     If,
      31             :     Switch,
      32             :     With,
      33             :     Catch,
      34             :     Try,
      35             :     Finally,
      36             :     ForLoopLexicalHead,
      37             :     ForLoop,
      38             :     ForInLoop,
      39             :     ForOfLoop,
      40             :     DoLoop,
      41             :     WhileLoop,
      42             :     Class,
      43             : 
      44             :     // Used only by BytecodeEmitter.
      45             :     Spread
      46             : };
      47             : 
      48             : static inline bool
      49        7294 : StatementKindIsLoop(StatementKind kind)
      50             : {
      51        5708 :     return kind == StatementKind::ForLoop ||
      52        5549 :            kind == StatementKind::ForInLoop ||
      53        4186 :            kind == StatementKind::ForOfLoop ||
      54        4126 :            kind == StatementKind::DoLoop ||
      55       10428 :            kind == StatementKind::WhileLoop ||
      56        7294 :            kind == StatementKind::Spread;
      57             : }
      58             : 
      59             : static inline bool
      60        3920 : StatementKindIsUnlabeledBreakTarget(StatementKind kind)
      61             : {
      62        3920 :     return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
      63             : }
      64             : 
      65             : // These flags apply to both global and function contexts.
      66             : class AnyContextFlags
      67             : {
      68             :     // This class's data is all private and so only visible to these friends.
      69             :     friend class SharedContext;
      70             : 
      71             :     // True if "use strict"; appears in the body instead of being inherited.
      72             :     bool hasExplicitUseStrict:1;
      73             : 
      74             :     // The (static) bindings of this script need to support dynamic name
      75             :     // read/write access. Here, 'dynamic' means dynamic dictionary lookup on
      76             :     // the scope chain for a dynamic set of keys. The primary examples are:
      77             :     //  - direct eval
      78             :     //  - function::
      79             :     //  - with
      80             :     // since both effectively allow any name to be accessed. Non-examples are:
      81             :     //  - upvars of nested functions
      82             :     //  - function statement
      83             :     // since the set of assigned name is known dynamically.
      84             :     //
      85             :     // Note: access through the arguments object is not considered dynamic
      86             :     // binding access since it does not go through the normal name lookup
      87             :     // mechanism. This is debatable and could be changed (although care must be
      88             :     // taken not to turn off the whole 'arguments' optimization). To answer the
      89             :     // more general "is this argument aliased" question, script->needsArgsObj
      90             :     // should be tested (see JSScript::argIsAliased).
      91             :     bool bindingsAccessedDynamically:1;
      92             : 
      93             :     // Whether this script, or any of its inner scripts contains a debugger
      94             :     // statement which could potentially read or write anywhere along the
      95             :     // scope chain.
      96             :     bool hasDebuggerStatement:1;
      97             : 
      98             :     // A direct eval occurs in the body of the script.
      99             :     bool hasDirectEval:1;
     100             : 
     101             :   public:
     102        7906 :     AnyContextFlags()
     103        7906 :      :  hasExplicitUseStrict(false),
     104             :         bindingsAccessedDynamically(false),
     105             :         hasDebuggerStatement(false),
     106        7906 :         hasDirectEval(false)
     107        7906 :     { }
     108             : };
     109             : 
     110             : class FunctionContextFlags
     111             : {
     112             :     // This class's data is all private and so only visible to these friends.
     113             :     friend class FunctionBox;
     114             : 
     115             :     // This function does something that can extend the set of bindings in its
     116             :     // call objects --- it does a direct eval in non-strict code, or includes a
     117             :     // function statement (as opposed to a function definition).
     118             :     //
     119             :     // This flag is *not* inherited by enclosed or enclosing functions; it
     120             :     // applies only to the function in whose flags it appears.
     121             :     //
     122             :     bool hasExtensibleScope:1;
     123             : 
     124             :     // Technically, every function has a binding named 'arguments'. Internally,
     125             :     // this binding is only added when 'arguments' is mentioned by the function
     126             :     // body. This flag indicates whether 'arguments' has been bound either
     127             :     // through implicit use:
     128             :     //   function f() { return arguments }
     129             :     // or explicit redeclaration:
     130             :     //   function f() { var arguments; return arguments }
     131             :     //
     132             :     // Note 1: overwritten arguments (function() { arguments = 3 }) will cause
     133             :     // this flag to be set but otherwise require no special handling:
     134             :     // 'arguments' is just a local variable and uses of 'arguments' will just
     135             :     // read the local's current slot which may have been assigned. The only
     136             :     // special semantics is that the initial value of 'arguments' is the
     137             :     // arguments object (not undefined, like normal locals).
     138             :     //
     139             :     // Note 2: if 'arguments' is bound as a formal parameter, there will be an
     140             :     // 'arguments' in Bindings, but, as the "LOCAL" in the name indicates, this
     141             :     // flag will not be set. This is because, as a formal, 'arguments' will
     142             :     // have no special semantics: the initial value is unconditionally the
     143             :     // actual argument (or undefined if nactual < nformal).
     144             :     //
     145             :     bool argumentsHasLocalBinding:1;
     146             : 
     147             :     // In many cases where 'arguments' has a local binding (as described above)
     148             :     // we do not need to actually create an arguments object in the function
     149             :     // prologue: instead we can analyze how 'arguments' is used (using the
     150             :     // simple dataflow analysis in analyzeSSA) to determine that uses of
     151             :     // 'arguments' can just read from the stack frame directly. However, the
     152             :     // dataflow analysis only looks at how JSOP_ARGUMENTS is used, so it will
     153             :     // be unsound in several cases. The frontend filters out such cases by
     154             :     // setting this flag which eagerly sets script->needsArgsObj to true.
     155             :     //
     156             :     bool definitelyNeedsArgsObj:1;
     157             : 
     158             :     bool needsHomeObject:1;
     159             :     bool isDerivedClassConstructor:1;
     160             : 
     161             :     // Whether this function has a .this binding. If true, we need to emit
     162             :     // JSOP_FUNCTIONTHIS in the prologue to initialize it.
     163             :     bool hasThisBinding:1;
     164             : 
     165             :     // Whether this function has nested functions.
     166             :     bool hasInnerFunctions:1;
     167             : 
     168             :   public:
     169        7633 :     FunctionContextFlags()
     170        7633 :      :  hasExtensibleScope(false),
     171             :         argumentsHasLocalBinding(false),
     172             :         definitelyNeedsArgsObj(false),
     173             :         needsHomeObject(false),
     174             :         isDerivedClassConstructor(false),
     175             :         hasThisBinding(false),
     176        7633 :         hasInnerFunctions(false)
     177        7633 :     { }
     178             : };
     179             : 
     180             : // List of directives that may be encountered in a Directive Prologue (ES5 15.1).
     181             : class Directives
     182             : {
     183             :     bool strict_;
     184             :     bool asmJS_;
     185             : 
     186             :   public:
     187        1951 :     explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
     188             :     explicit Directives(ParseContext* parent);
     189             : 
     190           0 :     void setStrict() { strict_ = true; }
     191        7906 :     bool strict() const { return strict_; }
     192             : 
     193           0 :     void setAsmJS() { asmJS_ = true; }
     194           0 :     bool asmJS() const { return asmJS_; }
     195             : 
     196           0 :     Directives& operator=(Directives rhs) {
     197           0 :         strict_ = rhs.strict_;
     198           0 :         asmJS_ = rhs.asmJS_;
     199           0 :         return *this;
     200             :     }
     201           0 :     bool operator==(const Directives& rhs) const {
     202           0 :         return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
     203             :     }
     204             :     bool operator!=(const Directives& rhs) const {
     205             :         return !(*this == rhs);
     206             :     }
     207             : };
     208             : 
     209             : // The kind of this-binding for the current scope. Note that arrow functions
     210             : // (and generator expression lambdas) have a lexical this-binding so their
     211             : // ThisBinding is the same as the ThisBinding of their enclosing scope and can
     212             : // be any value.
     213             : enum class ThisBinding { Global, Function, Module };
     214             : 
     215             : class GlobalSharedContext;
     216             : class EvalSharedContext;
     217             : class ModuleSharedContext;
     218             : 
     219             : /*
     220             :  * The struct SharedContext is part of the current parser context (see
     221             :  * ParseContext). It stores information that is reused between the parser and
     222             :  * the bytecode emitter.
     223             :  */
     224             : class SharedContext
     225             : {
     226             :   public:
     227             :     JSContext* const context;
     228             :     AnyContextFlags anyCxFlags;
     229             :     bool strictScript;
     230             :     bool localStrict;
     231             :     bool extraWarnings;
     232             : 
     233             :   protected:
     234             :     enum class Kind {
     235             :         FunctionBox,
     236             :         Global,
     237             :         Eval,
     238             :         Module
     239             :     };
     240             : 
     241             :     Kind kind_;
     242             : 
     243             :     ThisBinding thisBinding_;
     244             : 
     245             :     bool allowNewTarget_;
     246             :     bool allowSuperProperty_;
     247             :     bool allowSuperCall_;
     248             :     bool inWith_;
     249             :     bool needsThisTDZChecks_;
     250             : 
     251             :     void computeAllowSyntax(Scope* scope);
     252             :     void computeInWith(Scope* scope);
     253             :     void computeThisBinding(Scope* scope);
     254             : 
     255             :   public:
     256        7906 :     SharedContext(JSContext* cx, Kind kind, Directives directives, bool extraWarnings)
     257        7906 :       : context(cx),
     258             :         anyCxFlags(),
     259        7906 :         strictScript(directives.strict()),
     260             :         localStrict(false),
     261             :         extraWarnings(extraWarnings),
     262             :         kind_(kind),
     263             :         thisBinding_(ThisBinding::Global),
     264             :         allowNewTarget_(false),
     265             :         allowSuperProperty_(false),
     266             :         allowSuperCall_(false),
     267             :         inWith_(false),
     268       15812 :         needsThisTDZChecks_(false)
     269        7906 :     { }
     270             : 
     271             :     // If this is the outermost SharedContext, the Scope that encloses
     272             :     // it. Otherwise nullptr.
     273             :     virtual Scope* compilationEnclosingScope() const = 0;
     274             : 
     275      747800 :     bool isFunctionBox() const { return kind_ == Kind::FunctionBox; }
     276             :     inline FunctionBox* asFunctionBox();
     277        3852 :     bool isModuleContext() const { return kind_ == Kind::Module; }
     278             :     inline ModuleSharedContext* asModuleContext();
     279       82873 :     bool isGlobalContext() const { return kind_ == Kind::Global; }
     280             :     inline GlobalSharedContext* asGlobalContext();
     281        3075 :     bool isEvalContext() const { return kind_ == Kind::Eval; }
     282             :     inline EvalSharedContext* asEvalContext();
     283             : 
     284       20306 :     ThisBinding thisBinding()          const { return thisBinding_; }
     285             : 
     286        1564 :     bool allowNewTarget()              const { return allowNewTarget_; }
     287         858 :     bool allowSuperProperty()          const { return allowSuperProperty_; }
     288         847 :     bool allowSuperCall()              const { return allowSuperCall_; }
     289        6219 :     bool inWith()                      const { return inWith_; }
     290        7807 :     bool needsThisTDZChecks()          const { return needsThisTDZChecks_; }
     291             : 
     292        5680 :     bool hasExplicitUseStrict()        const { return anyCxFlags.hasExplicitUseStrict; }
     293       30581 :     bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
     294        8252 :     bool hasDebuggerStatement()        const { return anyCxFlags.hasDebuggerStatement; }
     295        8242 :     bool hasDirectEval()               const { return anyCxFlags.hasDirectEval; }
     296             : 
     297         109 :     void setExplicitUseStrict()           { anyCxFlags.hasExplicitUseStrict        = true; }
     298           2 :     void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
     299           0 :     void setHasDebuggerStatement()        { anyCxFlags.hasDebuggerStatement        = true; }
     300           2 :     void setHasDirectEval()               { anyCxFlags.hasDirectEval               = true; }
     301             : 
     302             :     inline bool allBindingsClosedOver();
     303             : 
     304      104582 :     bool strict() const {
     305      104582 :         return strictScript || localStrict;
     306             :     }
     307         128 :     bool setLocalStrictMode(bool strict) {
     308         128 :         bool retVal = localStrict;
     309         128 :         localStrict = strict;
     310         128 :         return retVal;
     311             :     }
     312             : 
     313             :     // JSOPTION_EXTRA_WARNINGS warnings or strict mode errors.
     314       29110 :     bool needStrictChecks() const {
     315       29110 :         return strict() || extraWarnings;
     316             :     }
     317             : 
     318             :     bool isDotVariable(JSAtom* atom) const {
     319             :         return atom == context->names().dotGenerator || atom == context->names().dotThis;
     320             :     }
     321             : };
     322             : 
     323         267 : class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext
     324             : {
     325             :     ScopeKind scopeKind_;
     326             : 
     327             :   public:
     328             :     Rooted<GlobalScope::Data*> bindings;
     329             : 
     330         267 :     GlobalSharedContext(JSContext* cx, ScopeKind scopeKind, Directives directives,
     331             :                         bool extraWarnings)
     332         267 :       : SharedContext(cx, Kind::Global, directives, extraWarnings),
     333             :         scopeKind_(scopeKind),
     334         267 :         bindings(cx)
     335             :     {
     336         267 :         MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
     337         267 :         thisBinding_ = ThisBinding::Global;
     338         267 :     }
     339             : 
     340         266 :     Scope* compilationEnclosingScope() const override {
     341         266 :         return nullptr;
     342             :     }
     343             : 
     344         526 :     ScopeKind scopeKind() const {
     345         526 :         return scopeKind_;
     346             :     }
     347             : };
     348             : 
     349             : inline GlobalSharedContext*
     350         533 : SharedContext::asGlobalContext()
     351             : {
     352         533 :     MOZ_ASSERT(isGlobalContext());
     353         533 :     return static_cast<GlobalSharedContext*>(this);
     354             : }
     355             : 
     356           2 : class MOZ_STACK_CLASS EvalSharedContext : public SharedContext
     357             : {
     358             :     RootedScope enclosingScope_;
     359             : 
     360             :   public:
     361             :     Rooted<EvalScope::Data*> bindings;
     362             : 
     363             :     EvalSharedContext(JSContext* cx, JSObject* enclosingEnv, Scope* enclosingScope,
     364             :                       Directives directives, bool extraWarnings);
     365             : 
     366           2 :     Scope* compilationEnclosingScope() const override {
     367           2 :         return enclosingScope_;
     368             :     }
     369             : };
     370             : 
     371             : inline EvalSharedContext*
     372           4 : SharedContext::asEvalContext()
     373             : {
     374           4 :     MOZ_ASSERT(isEvalContext());
     375           4 :     return static_cast<EvalSharedContext*>(this);
     376             : }
     377             : 
     378             : class FunctionBox : public ObjectBox, public SharedContext
     379             : {
     380             :     // The parser handles tracing the fields below via the ObjectBox linked
     381             :     // list.
     382             : 
     383             :     Scope* enclosingScope_;
     384             : 
     385             :     // Names from the named lambda scope, if a named lambda.
     386             :     LexicalScope::Data* namedLambdaBindings_;
     387             : 
     388             :     // Names from the function scope.
     389             :     FunctionScope::Data* functionScopeBindings_;
     390             : 
     391             :     // Names from the extra 'var' scope of the function, if the parameter list
     392             :     // has expressions.
     393             :     VarScope::Data* extraVarScopeBindings_;
     394             : 
     395             :     void initWithEnclosingScope(Scope* enclosingScope);
     396             : 
     397             :   public:
     398             :     ParseNode*      functionNode;           /* back pointer used by asm.js for error messages */
     399             :     uint32_t        bufStart;
     400             :     uint32_t        bufEnd;
     401             :     uint32_t        startLine;
     402             :     uint32_t        startColumn;
     403             :     uint32_t        toStringStart;
     404             :     uint32_t        toStringEnd;
     405             :     uint16_t        length;
     406             : 
     407             :     uint8_t         generatorKindBits_;     /* The GeneratorKind of this function. */
     408             :     uint8_t         asyncKindBits_;         /* The FunctionAsyncKind of this function. */
     409             : 
     410             :     bool            isGenexpLambda:1;       /* lambda from generator expression */
     411             :     bool            hasDestructuringArgs:1; /* parameter list contains destructuring expression */
     412             :     bool            hasParameterExprs:1;    /* parameter list contains expressions */
     413             :     bool            hasDirectEvalInParameterExpr:1; /* parameter list contains direct eval */
     414             :     bool            hasDuplicateParameters:1; /* parameter list contains duplicate names */
     415             :     bool            useAsm:1;               /* see useAsmOrInsideUseAsm */
     416             :     bool            insideUseAsm:1;         /* see useAsmOrInsideUseAsm */
     417             :     bool            isAnnexB:1;             /* need to emit a synthesized Annex B assignment */
     418             :     bool            wasEmitted:1;           /* Bytecode has been emitted for this function. */
     419             : 
     420             :     // Fields for use in heuristics.
     421             :     bool            declaredArguments:1;    /* the Parser declared 'arguments' */
     422             :     bool            usesArguments:1;        /* contains a free use of 'arguments' */
     423             :     bool            usesApply:1;            /* contains an f.apply() call */
     424             :     bool            usesThis:1;             /* contains 'this' */
     425             :     bool            usesReturn:1;           /* contains a 'return' statement */
     426             :     bool            hasRest_:1;             /* has rest parameter */
     427             :     bool            isExprBody_:1;          /* arrow function with expression
     428             :                                              * body or expression closure:
     429             :                                              * function(x) x*x */
     430             : 
     431             :     FunctionContextFlags funCxFlags;
     432             : 
     433             :     FunctionBox(JSContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
     434             :                 uint32_t toStringStart, Directives directives, bool extraWarnings,
     435             :                 GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
     436             : 
     437        6973 :     MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
     438        6973 :         MOZ_ASSERT(context->keepAtoms);
     439        6973 :         return MutableHandle<LexicalScope::Data*>::fromMarkedLocation(&namedLambdaBindings_);
     440             :     }
     441             : 
     442       16381 :     MutableHandle<FunctionScope::Data*> functionScopeBindings() {
     443       16381 :         MOZ_ASSERT(context->keepAtoms);
     444       16381 :         return MutableHandle<FunctionScope::Data*>::fromMarkedLocation(&functionScopeBindings_);
     445             :     }
     446             : 
     447         599 :     MutableHandle<VarScope::Data*> extraVarScopeBindings() {
     448         599 :         MOZ_ASSERT(context->keepAtoms);
     449         599 :         return MutableHandle<VarScope::Data*>::fromMarkedLocation(&extraVarScopeBindings_);
     450             :     }
     451             : 
     452             :     void initFromLazyFunction();
     453             :     void initStandaloneFunction(Scope* enclosingScope);
     454             :     void initWithEnclosingParseContext(ParseContext* enclosing, FunctionSyntaxKind kind);
     455             : 
     456      107004 :     JSFunction* function() const { return &object->as<JSFunction>(); }
     457             : 
     458        5319 :     Scope* compilationEnclosingScope() const override {
     459             :         // This method is used to distinguish the outermost SharedContext. If
     460             :         // a FunctionBox is the outermost SharedContext, it must be a lazy
     461             :         // function.
     462        5319 :         MOZ_ASSERT_IF(function()->isInterpretedLazy(),
     463             :                       enclosingScope_ == function()->lazyScript()->enclosingScope());
     464        5319 :         return enclosingScope_;
     465             :     }
     466             : 
     467        5404 :     bool needsCallObjectRegardlessOfBindings() const {
     468       10806 :         return hasExtensibleScope() ||
     469       10791 :                needsHomeObject() ||
     470       10765 :                isDerivedClassConstructor() ||
     471       10737 :                isStarGenerator() ||
     472       16126 :                isLegacyGenerator() ||
     473       10765 :                isAsync();
     474             :     }
     475             : 
     476       10992 :     bool hasExtraBodyVarScope() const {
     477       11853 :         return hasParameterExprs &&
     478         786 :                (extraVarScopeBindings_ ||
     479       11229 :                 needsExtraBodyVarEnvironmentRegardlessOfBindings());
     480             :     }
     481             : 
     482         341 :     bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
     483         341 :         MOZ_ASSERT(hasParameterExprs);
     484         341 :         return hasExtensibleScope() || needsDotGeneratorName();
     485             :     }
     486             : 
     487        6009 :     bool isLikelyConstructorWrapper() const {
     488        6009 :         return usesArguments && usesApply && usesThis && !usesReturn;
     489             :     }
     490             : 
     491      118228 :     GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
     492       33724 :     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
     493       40218 :     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
     494       79512 :     FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
     495             : 
     496       11569 :     bool needsFinalYield() const {
     497       11569 :         return isStarGenerator() || isLegacyGenerator() || isAsync();
     498             :     }
     499         341 :     bool needsDotGeneratorName() const {
     500         341 :         return isStarGenerator() || isLegacyGenerator() || isAsync();
     501             :     }
     502        6306 :     bool needsIteratorResult() const {
     503        6306 :         return isStarGenerator();
     504             :     }
     505             : 
     506       72075 :     bool isAsync() const { return asyncKind() == AsyncFunction; }
     507           0 :     bool isArrow() const { return function()->isArrow(); }
     508             : 
     509       14063 :     bool hasRest() const { return hasRest_; }
     510          73 :     void setHasRest() {
     511          73 :         hasRest_ = true;
     512          73 :     }
     513             : 
     514        7445 :     bool isExprBody() const { return isExprBody_; }
     515         609 :     void setIsExprBody() {
     516         609 :         isExprBody_ = true;
     517         609 :     }
     518             : 
     519           0 :     void setGeneratorKind(GeneratorKind kind) {
     520             :         // A generator kind can be set at initialization, or when "yield" is
     521             :         // first seen.  In both cases the transition can only happen from
     522             :         // NotGenerator.
     523           0 :         MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
     524           0 :         generatorKindBits_ = GeneratorKindAsBits(kind);
     525           0 :     }
     526             : 
     527       16475 :     bool hasExtensibleScope()        const { return funCxFlags.hasExtensibleScope; }
     528       12837 :     bool hasThisBinding()            const { return funCxFlags.hasThisBinding; }
     529       11162 :     bool argumentsHasLocalBinding()  const { return funCxFlags.argumentsHasLocalBinding; }
     530        5405 :     bool definitelyNeedsArgsObj()    const { return funCxFlags.definitelyNeedsArgsObj; }
     531       15810 :     bool needsHomeObject()           const { return funCxFlags.needsHomeObject; }
     532       28164 :     bool isDerivedClassConstructor() const { return funCxFlags.isDerivedClassConstructor; }
     533        5405 :     bool hasInnerFunctions()         const { return funCxFlags.hasInnerFunctions; }
     534             : 
     535           2 :     void setHasExtensibleScope()           { funCxFlags.hasExtensibleScope       = true; }
     536        3128 :     void setHasThisBinding()               { funCxFlags.hasThisBinding           = true; }
     537         270 :     void setArgumentsHasLocalBinding()     { funCxFlags.argumentsHasLocalBinding = true; }
     538           3 :     void setDefinitelyNeedsArgsObj()       { MOZ_ASSERT(funCxFlags.argumentsHasLocalBinding);
     539           3 :                                              funCxFlags.definitelyNeedsArgsObj   = true; }
     540          19 :     void setNeedsHomeObject()              { MOZ_ASSERT(function()->allowSuperProperty());
     541          19 :                                              funCxFlags.needsHomeObject          = true; }
     542          19 :     void setDerivedClassConstructor()      { MOZ_ASSERT(function()->isClassConstructor());
     543          19 :                                              funCxFlags.isDerivedClassConstructor = true; }
     544        1120 :     void setHasInnerFunctions()            { funCxFlags.hasInnerFunctions         = true; }
     545             : 
     546        1187 :     bool hasSimpleParameterList() const {
     547        1187 :         return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
     548             :     }
     549             : 
     550        5406 :     bool hasMappedArgsObj() const {
     551        5406 :         return !strict() && hasSimpleParameterList();
     552             :     }
     553             : 
     554             :     // Return whether this or an enclosing function is being parsed and
     555             :     // validated as asm.js. Note: if asm.js validation fails, this will be false
     556             :     // while the function is being reparsed. This flag can be used to disable
     557             :     // certain parsing features that are necessary in general, but unnecessary
     558             :     // for validated asm.js.
     559      124323 :     bool useAsmOrInsideUseAsm() const {
     560      124323 :         return useAsm || insideUseAsm;
     561             :     }
     562             : 
     563        7373 :     void setStart(const TokenStream& tokenStream) {
     564             :         // Token positions are already offset from the start column in
     565             :         // CompileOptions. bufStart and toStringStart, however, refer to
     566             :         // absolute positions within the ScriptSource buffer, and need to
     567             :         // de-offset from the starting column.
     568        7373 :         uint32_t offset = tokenStream.currentToken().pos.begin;
     569        7373 :         uint32_t sourceStartColumn = tokenStream.options().sourceStartColumn;
     570             : 
     571        7373 :         MOZ_ASSERT(offset >= sourceStartColumn);
     572        7373 :         MOZ_ASSERT(toStringStart >= sourceStartColumn);
     573        7373 :         toStringStart -= sourceStartColumn;
     574        7373 :         bufStart = offset - sourceStartColumn;
     575        7373 :         tokenStream.srcCoords.lineNumAndColumnIndex(offset, &startLine, &startColumn);
     576        7373 :     }
     577             : 
     578        7373 :     void setEnd(const TokenStream& tokenStream) {
     579             :         // For all functions except class constructors, the buffer and
     580             :         // toString ending positions are the same. Class constructors override
     581             :         // the toString ending position with the end of the class definition.
     582             :         //
     583             :         // Offsets are de-offset for the same reason as in setStart above.
     584        7373 :         uint32_t offset = tokenStream.currentToken().pos.end;
     585        7373 :         uint32_t sourceStartColumn = tokenStream.options().sourceStartColumn;
     586             : 
     587        7373 :         MOZ_ASSERT(offset >= sourceStartColumn);
     588        7373 :         bufEnd = offset - sourceStartColumn;
     589        7373 :         toStringEnd = bufEnd;
     590        7373 :     }
     591             : 
     592             :     void trace(JSTracer* trc) override;
     593             : };
     594             : 
     595             : inline FunctionBox*
     596      385724 : SharedContext::asFunctionBox()
     597             : {
     598      385724 :     MOZ_ASSERT(isFunctionBox());
     599      385724 :     return static_cast<FunctionBox*>(this);
     600             : }
     601             : 
     602           0 : class MOZ_STACK_CLASS ModuleSharedContext : public SharedContext
     603             : {
     604             :     RootedModuleObject module_;
     605             :     RootedScope enclosingScope_;
     606             : 
     607             :   public:
     608             :     Rooted<ModuleScope::Data*> bindings;
     609             :     ModuleBuilder& builder;
     610             : 
     611             :     ModuleSharedContext(JSContext* cx, ModuleObject* module, Scope* enclosingScope,
     612             :                         ModuleBuilder& builder);
     613             : 
     614           0 :     HandleModuleObject module() const { return module_; }
     615           0 :     Scope* compilationEnclosingScope() const override { return enclosingScope_; }
     616             : };
     617             : 
     618             : inline ModuleSharedContext*
     619           0 : SharedContext::asModuleContext()
     620             : {
     621           0 :     MOZ_ASSERT(isModuleContext());
     622           0 :     return static_cast<ModuleSharedContext*>(this);
     623             : }
     624             : 
     625             : // In generators, we treat all bindings as closed so that they get stored on
     626             : // the heap.  This way there is less information to copy off the stack when
     627             : // suspending, and back on when resuming.  It also avoids the need to create
     628             : // and invalidate DebugScope proxies for unaliased locals in a generator
     629             : // frame, as the generator frame will be copied out to the heap and released
     630             : // only by GC.
     631             : inline bool
     632        9131 : SharedContext::allBindingsClosedOver()
     633             : {
     634       18640 :     return bindingsAccessedDynamically() ||
     635       17945 :            (isFunctionBox() &&
     636       17587 :             (asFunctionBox()->isStarGenerator() ||
     637       17542 :              asFunctionBox()->isLegacyGenerator() ||
     638       17902 :              asFunctionBox()->isAsync()));
     639             : }
     640             : 
     641             : } // namespace frontend
     642             : } // namespace js
     643             : 
     644             : #endif /* frontend_SharedContext_h */

Generated by: LCOV version 1.13