LCOV - code coverage report
Current view: top level - js/src/vm - EnvironmentObject.h (source / functions) Hit Total Coverage
Test: output.info Lines: 107 159 67.3 %
Date: 2017-07-14 16:53:18 Functions: 35 60 58.3 %
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 vm_EnvironmentObject_h
       8             : #define vm_EnvironmentObject_h
       9             : 
      10             : #include "jscntxt.h"
      11             : #include "jsobj.h"
      12             : #include "jsweakmap.h"
      13             : 
      14             : #include "builtin/ModuleObject.h"
      15             : #include "frontend/NameAnalysisTypes.h"
      16             : #include "gc/Barrier.h"
      17             : #include "js/GCHashTable.h"
      18             : #include "vm/ArgumentsObject.h"
      19             : #include "vm/ProxyObject.h"
      20             : #include "vm/Scope.h"
      21             : 
      22             : namespace js {
      23             : 
      24             : class ModuleObject;
      25             : typedef Handle<ModuleObject*> HandleModuleObject;
      26             : 
      27             : /*
      28             :  * Return a shape representing the static scope containing the variable
      29             :  * accessed by the ALIASEDVAR op at 'pc'.
      30             :  */
      31             : extern Shape*
      32             : EnvironmentCoordinateToEnvironmentShape(JSScript* script, jsbytecode* pc);
      33             : 
      34             : /* Return the name being accessed by the given ALIASEDVAR op. */
      35             : extern PropertyName*
      36             : EnvironmentCoordinateName(EnvironmentCoordinateNameCache& cache, JSScript* script, jsbytecode* pc);
      37             : 
      38             : /* Return the function script accessed by the given ALIASEDVAR op, or nullptr. */
      39             : extern JSScript*
      40             : EnvironmentCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
      41             : 
      42             : 
      43             : /*** Environment objects *****************************************************/
      44             : 
      45             : 
      46             : /*** Environment objects *****************************************************/
      47             : 
      48             : /*
      49             :  * About environments
      50             :  * ------------------
      51             :  *
      52             :  * (See also: ecma262 rev c7952de (19 Aug 2016) 8.1 "Lexical Environments".)
      53             :  *
      54             :  * Scoping in ES is specified in terms of "Environment Records". There's a
      55             :  * global Environment Record per realm, and a new Environment Record is created
      56             :  * whenever control enters a function, block, or other scope.
      57             :  *
      58             :  * A "Lexical Environment" is a list of nested Environment Records, innermost
      59             :  * first: everything that's in scope. Throughout SpiderMonkey, "environment"
      60             :  * means a Lexical Environment.
      61             :  *
      62             :  * N.B.: "Scope" means something different: a static scope, the compile-time
      63             :  * analogue of an environment. See Scope.h.
      64             :  *
      65             :  * How SpiderMonkey represents environments
      66             :  * ----------------------------------------
      67             :  *
      68             :  * Some environments are stored as JSObjects. Several kinds of objects
      69             :  * represent environments:
      70             :  *
      71             :  *   JSObject
      72             :  *    |
      73             :  *    +--NativeObject
      74             :  *    |   |
      75             :  *    |   +--EnvironmentObject             Engine-internal environment
      76             :  *    |   |   |
      77             :  *    |   |   +--CallObject                    Environment of entire function
      78             :  *    |   |   |
      79             :  *    |   |   +--ModuleEnvironmentObject       Module top-level environment
      80             :  *    |   |   |
      81             :  *    |   |   +--LexicalEnvironmentObject      Lexical (block) environment
      82             :  *    |   |   |   |
      83             :  *    |   |   |   +--NamedLambdaObject             Environment for `(function f(){...})`
      84             :  *    |   |   |                                        containing only a binding for `f`
      85             :  *    |   |   +--VarEnvironmentObject          See VarScope in Scope.h.
      86             :  *    |   |   |
      87             :  *    |   |   +--WithEnvironmentObject         Presents object properties as bindings
      88             :  *    |   |   |
      89             :  *    |   |   +--NonSyntacticVariablesObject   See "Non-syntactic environments" below
      90             :  *    |   |
      91             :  *    |   +--GlobalObject                  The global environment
      92             :  *    |
      93             :  *    +--ProxyObject
      94             :  *        |
      95             :  *        +--DebugEnvironmentProxy         Environment for debugger eval-in-frame
      96             :  *
      97             :  * EnvironmentObjects are technically real JSObjects but only belong on the
      98             :  * environment chain (that is, fp->environmentChain() or fun->environment()).
      99             :  * They are never exposed to scripts.
     100             :  *
     101             :  * Note that reserved slots in any base classes shown above are fixed for all
     102             :  * derived classes. So e.g. EnvironmentObject::enclosingEnvironment() can
     103             :  * simply access a fixed slot without further dynamic type information.
     104             :  *
     105             :  * When the current environment is represented by an object, the stack frame
     106             :  * has a pointer to that object (see AbstractFramePtr::environmentChain()).
     107             :  * However, that isn't always the case. Where possible, we store binding values
     108             :  * in JS stack slots. For block and function scopes where all bindings can be
     109             :  * stored in stack slots, nothing is allocated in the heap; there is no
     110             :  * environment object.
     111             :  *
     112             :  * Full information about the environment chain is always recoverable:
     113             :  * EnvironmentIter can do it, and we construct a fake environment for debugger
     114             :  * eval-in-frame (see "Debug environment objects" below).
     115             :  *
     116             :  * Syntactic Environments
     117             :  * ----------------------
     118             :  *
     119             :  * Environments may be syntactic, i.e., corresponding to source text, or
     120             :  * non-syntactic, i.e., specially created by embedding. The distinction is
     121             :  * necessary to maintain invariants about the environment chain: non-syntactic
     122             :  * environments may not occur in arbitrary positions in the chain.
     123             :  *
     124             :  * CallObject, ModuleEnvironmentObject, and LexicalEnvironmentObject always
     125             :  * represent syntactic environments. (CallObject is considered syntactic even
     126             :  * when it's used as the scope of strict eval code.) WithEnvironmentObject is
     127             :  * syntactic when it's used to represent the scope of a `with` block.
     128             :  *
     129             :  *
     130             :  * Non-syntactic Environments
     131             :  * --------------------------
     132             :  *
     133             :  * A non-syntactic environment is one that was not created due to JS source
     134             :  * code. On the scope chain, a single NonSyntactic GlobalScope maps to 0+
     135             :  * non-syntactic environment objects. This is contrasted with syntactic
     136             :  * environments, where each scope corresponds to 0 or 1 environment object.
     137             :  *
     138             :  * There are 3 kinds of dynamic environment objects:
     139             :  *
     140             :  * 1. WithEnvironmentObject
     141             :  *
     142             :  *    When the embedding compiles or executes a script, it has the option to
     143             :  *    pass in a vector of objects to be used as the initial env chain, ordered
     144             :  *    from outermost env to innermost env. Each of those objects is wrapped by
     145             :  *    a WithEnvironmentObject.
     146             :  *
     147             :  *    The innermost object passed in by the embedding becomes a qualified
     148             :  *    variables object that captures 'var' bindings. That is, it wraps the
     149             :  *    holder object of 'var' bindings.
     150             :  *
     151             :  *    Does not hold 'let' or 'const' bindings.
     152             :  *
     153             :  * 2. NonSyntacticVariablesObject
     154             :  *
     155             :  *    When the embedding wants qualified 'var' bindings and unqualified
     156             :  *    bareword assignments to go on a different object than the global
     157             :  *    object. While any object can be made into a qualified variables object,
     158             :  *    only the GlobalObject and NonSyntacticVariablesObject are considered
     159             :  *    unqualified variables objects.
     160             :  *
     161             :  *    Unlike WithEnvironmentObjects that delegate to the object they wrap,
     162             :  *    this object is itself the holder of 'var' bindings.
     163             :  *
     164             :  *    Does not hold 'let' or 'const' bindings.
     165             :  *
     166             :  * 3. LexicalEnvironmentObject
     167             :  *
     168             :  *    Each non-syntactic object used as a qualified variables object needs to
     169             :  *    enclose a non-syntactic LexicalEnvironmentObject to hold 'let' and
     170             :  *    'const' bindings. There is a bijection per compartment between the
     171             :  *    non-syntactic variables objects and their non-syntactic
     172             :  *    LexicalEnvironmentObjects.
     173             :  *
     174             :  *    Does not hold 'var' bindings.
     175             :  *
     176             :  * The embedding (Gecko) uses non-syntactic envs for various things, some of
     177             :  * which are detailed below. All env chain listings below are, from top to
     178             :  * bottom, outermost to innermost.
     179             :  *
     180             :  * A. Component loading
     181             :  *
     182             :  * Components may be loaded in "reuse loader global" mode, where to save on
     183             :  * memory, all JSMs and JS-implemented XPCOM modules are loaded into a single
     184             :  * global. Each individual JSMs are compiled as functions with their own
     185             :  * FakeBackstagePass. They have the following env chain:
     186             :  *
     187             :  *   BackstagePass global
     188             :  *       |
     189             :  *   Global lexical scope
     190             :  *       |
     191             :  *   WithEnvironmentObject wrapping FakeBackstagePass
     192             :  *       |
     193             :  *   LexicalEnvironmentObject
     194             :  *
     195             :  * B. Subscript loading
     196             :  *
     197             :  * Subscripts may be loaded into a target object. They have the following
     198             :  * env chain:
     199             :  *
     200             :  *   Loader global
     201             :  *       |
     202             :  *   Global lexical scope
     203             :  *       |
     204             :  *   WithEnvironmentObject wrapping target
     205             :  *       |
     206             :  *   LexicalEnvironmentObject
     207             :  *
     208             :  * C. Frame scripts
     209             :  *
     210             :  * XUL frame scripts are always loaded with a NonSyntacticVariablesObject as a
     211             :  * "polluting global". This is done exclusively in
     212             :  * js::ExecuteInGlobalAndReturnScope.
     213             :  *
     214             :  *   Loader global
     215             :  *       |
     216             :  *   Global lexical scope
     217             :  *       |
     218             :  *   NonSyntacticVariablesObject
     219             :  *       |
     220             :  *   LexicalEnvironmentObject
     221             :  *
     222             :  * D. XBL and DOM event handlers
     223             :  *
     224             :  * XBL methods are compiled as functions with XUL elements on the env chain,
     225             :  * and DOM event handlers are compiled as functions with HTML elements on the
     226             :  * env chain. For a chain of elements e0,...,eN:
     227             :  *
     228             :  *      ...
     229             :  *       |
     230             :  *   WithEnvironmentObject wrapping eN
     231             :  *       |
     232             :  *      ...
     233             :  *       |
     234             :  *   WithEnvironmentObject wrapping e0
     235             :  *       |
     236             :  *   LexicalEnvironmentObject
     237             :  *
     238             :  */
     239             : 
     240             : class EnvironmentObject : public NativeObject
     241             : {
     242             :   protected:
     243             :     // The enclosing environment. Either another EnvironmentObject, a
     244             :     // GlobalObject, or a non-syntactic environment object.
     245             :     static const uint32_t ENCLOSING_ENV_SLOT = 0;
     246             : 
     247             :     inline void setAliasedBinding(JSContext* cx, uint32_t slot, PropertyName* name,
     248             :                                   const Value& v);
     249             : 
     250           0 :     void setEnclosingEnvironment(JSObject* enclosing) {
     251           0 :         setReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
     252           0 :     }
     253             : 
     254             :   public:
     255             :     // Since every env chain terminates with a global object, whether
     256             :     // GlobalObject or a non-syntactic one, and since those objects do not
     257             :     // derive EnvironmentObject (they have completely different layouts), the
     258             :     // enclosing environment of an EnvironmentObject is necessarily non-null.
     259      170237 :     JSObject& enclosingEnvironment() const {
     260      170237 :         return getReservedSlot(ENCLOSING_ENV_SLOT).toObject();
     261             :     }
     262             : 
     263        8501 :     void initEnclosingEnvironment(JSObject* enclosing) {
     264        8501 :         initReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
     265        8501 :     }
     266             : 
     267             :     // Get or set a name contained in this environment.
     268        7223 :     const Value& aliasedBinding(EnvironmentCoordinate ec) {
     269        7223 :         return getSlot(ec.slot());
     270             :     }
     271             : 
     272           0 :     const Value& aliasedBinding(const BindingIter& bi) {
     273           0 :         MOZ_ASSERT(bi.location().kind() == BindingLocation::Kind::Environment);
     274           0 :         return getSlot(bi.location().slot());
     275             :     }
     276             : 
     277             :     inline void setAliasedBinding(JSContext* cx, EnvironmentCoordinate ec, PropertyName* name,
     278             :                                   const Value& v);
     279             : 
     280             :     inline void setAliasedBinding(JSContext* cx, const BindingIter& bi, const Value& v);
     281             : 
     282             :     // For JITs.
     283         303 :     static size_t offsetOfEnclosingEnvironment() {
     284         303 :         return getFixedSlotOffset(ENCLOSING_ENV_SLOT);
     285             :     }
     286             : 
     287           7 :     static uint32_t enclosingEnvironmentSlot() {
     288           7 :         return ENCLOSING_ENV_SLOT;
     289             :     }
     290             : };
     291             : 
     292             : class CallObject : public EnvironmentObject
     293             : {
     294             :   protected:
     295             :     static const uint32_t CALLEE_SLOT = 1;
     296             : 
     297             :     static CallObject* create(JSContext* cx, HandleScript script, HandleFunction callee,
     298             :                               HandleObject enclosing);
     299             : 
     300             :   public:
     301             :     static const uint32_t RESERVED_SLOTS = 2;
     302             :     static const Class class_;
     303             : 
     304             :     /* These functions are internal and are exposed only for JITs. */
     305             : 
     306             :     /*
     307             :      * Construct a bare-bones call object given a shape and a non-singleton
     308             :      * group.  The call object must be further initialized to be usable.
     309             :      */
     310             :     static CallObject* create(JSContext* cx, HandleShape shape, HandleObjectGroup group);
     311             : 
     312             :     /*
     313             :      * Construct a bare-bones call object given a shape and make it into
     314             :      * a singleton.  The call object must be initialized to be usable.
     315             :      */
     316             :     static CallObject* createSingleton(JSContext* cx, HandleShape shape);
     317             : 
     318             :     static CallObject* createTemplateObject(JSContext* cx, HandleScript script,
     319             :                                             HandleObject enclosing, gc::InitialHeap heap);
     320             : 
     321             :     static CallObject* create(JSContext* cx, HandleFunction callee, HandleObject enclosing);
     322             :     static CallObject* create(JSContext* cx, AbstractFramePtr frame);
     323             : 
     324             :     static CallObject* createHollowForDebug(JSContext* cx, HandleFunction callee);
     325             : 
     326             :     /*
     327             :      * When an aliased formal (var accessed by nested closures) is also
     328             :      * aliased by the arguments object, it must of course exist in one
     329             :      * canonical location and that location is always the CallObject. For this
     330             :      * to work, the ArgumentsObject stores special MagicValue in its array for
     331             :      * forwarded-to-CallObject variables. This MagicValue's payload is the
     332             :      * slot of the CallObject to access.
     333             :      */
     334           0 :     const Value& aliasedFormalFromArguments(const Value& argsValue) {
     335           0 :         return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
     336             :     }
     337             :     inline void setAliasedFormalFromArguments(JSContext* cx, const Value& argsValue, jsid id,
     338             :                                               const Value& v);
     339             : 
     340        4773 :     JSFunction& callee() const {
     341        4773 :         return getReservedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
     342             :     }
     343             : 
     344             :     /* For jit access. */
     345           0 :     static size_t offsetOfCallee() {
     346           0 :         return getFixedSlotOffset(CALLEE_SLOT);
     347             :     }
     348             : 
     349           4 :     static size_t calleeSlot() {
     350           4 :         return CALLEE_SLOT;
     351             :     }
     352             : };
     353             : 
     354             : class VarEnvironmentObject : public EnvironmentObject
     355             : {
     356             :     static const uint32_t SCOPE_SLOT = 1;
     357             : 
     358             :     static VarEnvironmentObject* create(JSContext* cx, HandleShape shape, HandleObject enclosing,
     359             :                                         gc::InitialHeap heap);
     360             : 
     361          41 :     void initScope(Scope* scope) {
     362          41 :         initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
     363          41 :     }
     364             : 
     365             :   public:
     366             :     static const uint32_t RESERVED_SLOTS = 2;
     367             :     static const Class class_;
     368             : 
     369             :     static VarEnvironmentObject* create(JSContext* cx, HandleScope scope, AbstractFramePtr frame);
     370             :     static VarEnvironmentObject* createHollowForDebug(JSContext* cx, Handle<VarScope*> scope);
     371             : 
     372         126 :     Scope& scope() const {
     373         126 :         Value v = getReservedSlot(SCOPE_SLOT);
     374         126 :         MOZ_ASSERT(v.isPrivateGCThing());
     375         126 :         Scope& s = *static_cast<Scope*>(v.toGCThing());
     376         126 :         MOZ_ASSERT(s.is<VarScope>() || s.is<EvalScope>());
     377         126 :         return s;
     378             :     }
     379             : 
     380           0 :     bool isForEval() const {
     381           0 :         return scope().is<EvalScope>();
     382             :     }
     383             : };
     384             : 
     385             : class ModuleEnvironmentObject : public EnvironmentObject
     386             : {
     387             :     static const uint32_t MODULE_SLOT = 1;
     388             : 
     389             :     static const ObjectOps objectOps_;
     390             :     static const ClassOps classOps_;
     391             : 
     392             :   public:
     393             :     static const Class class_;
     394             : 
     395             :     static const uint32_t RESERVED_SLOTS = 2;
     396             : 
     397             :     static ModuleEnvironmentObject* create(JSContext* cx, HandleModuleObject module);
     398             :     ModuleObject& module();
     399             :     IndirectBindingMap& importBindings();
     400             : 
     401             :     bool createImportBinding(JSContext* cx, HandleAtom importName, HandleModuleObject module,
     402             :                              HandleAtom exportName);
     403             : 
     404             :     bool hasImportBinding(HandlePropertyName name);
     405             : 
     406             :     bool lookupImport(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut);
     407             : 
     408             :     void fixEnclosingEnvironmentAfterCompartmentMerge(GlobalObject& global);
     409             : 
     410             :   private:
     411             :     static bool lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
     412             :                                MutableHandleObject objp, MutableHandle<PropertyResult> propp);
     413             :     static bool hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
     414             :     static bool getProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
     415             :                             MutableHandleValue vp);
     416             :     static bool setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
     417             :                             HandleValue receiver, JS::ObjectOpResult& result);
     418             :     static bool getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
     419             :                                          MutableHandle<PropertyDescriptor> desc);
     420             :     static bool deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
     421             :                                ObjectOpResult& result);
     422             :     static bool newEnumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
     423             :                              bool enumerableOnly);
     424             : };
     425             : 
     426             : typedef Rooted<ModuleEnvironmentObject*> RootedModuleEnvironmentObject;
     427             : typedef Handle<ModuleEnvironmentObject*> HandleModuleEnvironmentObject;
     428             : typedef MutableHandle<ModuleEnvironmentObject*> MutableHandleModuleEnvironmentObject;
     429             : 
     430             : class WasmFunctionCallObject : public EnvironmentObject
     431             : {
     432             :     // Currently WasmFunctionCallObjects do not use their scopes in a
     433             :     // meaningful way. However, it is an invariant of DebugEnvironments that
     434             :     // environments kept in those maps have live scopes, thus this strong
     435             :     // reference.
     436             :     static const uint32_t SCOPE_SLOT = 1;
     437             : 
     438             :   public:
     439             :     static const Class class_;
     440             : 
     441             :     static const uint32_t RESERVED_SLOTS = 2;
     442             : 
     443             :     static WasmFunctionCallObject* createHollowForDebug(JSContext* cx,
     444             :                                                         Handle<WasmFunctionScope*> scope);
     445           0 :     WasmFunctionScope& scope() const {
     446           0 :         Value v = getReservedSlot(SCOPE_SLOT);
     447           0 :         MOZ_ASSERT(v.isPrivateGCThing());
     448           0 :         return *static_cast<WasmFunctionScope*>(v.toGCThing());
     449             :     }
     450             : };
     451             : 
     452             : class LexicalEnvironmentObject : public EnvironmentObject
     453             : {
     454             :     // Global and non-syntactic lexical environments need to store a 'this'
     455             :     // value and all other lexical environments have a fixed shape and store a
     456             :     // backpointer to the LexicalScope.
     457             :     //
     458             :     // Since the two sets are disjoint, we only use one slot to save space.
     459             :     static const unsigned THIS_VALUE_OR_SCOPE_SLOT = 1;
     460             : 
     461             :   public:
     462             :     static const unsigned RESERVED_SLOTS = 2;
     463             :     static const Class class_;
     464             : 
     465             :   private:
     466             :     static LexicalEnvironmentObject* createTemplateObject(JSContext* cx, HandleShape shape,
     467             :                                                           HandleObject enclosing,
     468             :                                                           gc::InitialHeap heap);
     469             : 
     470         419 :     void initThisValue(JSObject* obj) {
     471         419 :         MOZ_ASSERT(isGlobal() || !isSyntactic());
     472         419 :         initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, GetThisValue(obj));
     473         419 :     }
     474             : 
     475        2089 :     void initScopeUnchecked(LexicalScope* scope) {
     476        2089 :         initReservedSlot(THIS_VALUE_OR_SCOPE_SLOT, PrivateGCThingValue(scope));
     477        2089 :     }
     478             : 
     479             :     void initScope(LexicalScope* scope) {
     480             :         MOZ_ASSERT(!isGlobal());
     481             :         MOZ_ASSERT(isSyntactic());
     482             :         initScopeUnchecked(scope);
     483             :     }
     484             : 
     485             :   public:
     486             :     static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
     487             :                                             HandleObject enclosing, gc::InitialHeap heap);
     488             :     static LexicalEnvironmentObject* create(JSContext* cx, Handle<LexicalScope*> scope,
     489             :                                             AbstractFramePtr frame);
     490             :     static LexicalEnvironmentObject* createGlobal(JSContext* cx, Handle<GlobalObject*> global);
     491             :     static LexicalEnvironmentObject* createNonSyntactic(JSContext* cx, HandleObject enclosing);
     492             :     static LexicalEnvironmentObject* createHollowForDebug(JSContext* cx,
     493             :                                                           Handle<LexicalScope*> scope);
     494             : 
     495             :     // Create a new LexicalEnvironmentObject with the same enclosing env and
     496             :     // variable values as this.
     497             :     static LexicalEnvironmentObject* clone(JSContext* cx, Handle<LexicalEnvironmentObject*> env);
     498             : 
     499             :     // Create a new LexicalEnvironmentObject with the same enclosing env as
     500             :     // this, with all variables uninitialized.
     501             :     static LexicalEnvironmentObject* recreate(JSContext* cx, Handle<LexicalEnvironmentObject*> env);
     502             : 
     503             :     // For non-extensible lexical environments, the LexicalScope that created
     504             :     // this environment. Otherwise asserts.
     505        2585 :     LexicalScope& scope() const {
     506        2585 :         Value v = getReservedSlot(THIS_VALUE_OR_SCOPE_SLOT);
     507        2585 :         MOZ_ASSERT(!isExtensible() && v.isPrivateGCThing());
     508        2585 :         return *static_cast<LexicalScope*>(v.toGCThing());
     509             :     }
     510             : 
     511             :     // Is this the global lexical scope?
     512       50834 :     bool isGlobal() const {
     513       50834 :         return enclosingEnvironment().is<GlobalObject>();
     514             :     }
     515             : 
     516        2895 :     GlobalObject& global() const {
     517        2895 :         return enclosingEnvironment().as<GlobalObject>();
     518             :     }
     519             : 
     520             :     // Global and non-syntactic lexical scopes are extensible. All other
     521             :     // lexical scopes are not.
     522             :     bool isExtensible() const;
     523             : 
     524             :     // Is this a syntactic (i.e. corresponds to a source text) lexical
     525             :     // environment?
     526       28857 :     bool isSyntactic() const {
     527       28857 :         return !isExtensible() || isGlobal();
     528             :     }
     529             : 
     530             :     // For extensible lexical environments, the 'this' value for its
     531             :     // scope. Otherwise asserts.
     532             :     Value thisValue() const;
     533             : };
     534             : 
     535             : class NamedLambdaObject : public LexicalEnvironmentObject
     536             : {
     537             :     static NamedLambdaObject* create(JSContext* cx, HandleFunction callee,
     538             :                                      HandleFunction replacement,
     539             :                                      HandleObject enclosing, gc::InitialHeap heap);
     540             : 
     541             :   public:
     542             :     static NamedLambdaObject* createTemplateObject(JSContext* cx, HandleFunction callee,
     543             :                                                    gc::InitialHeap heap);
     544             : 
     545             :     static NamedLambdaObject* create(JSContext* cx, AbstractFramePtr frame);
     546             :     static NamedLambdaObject* create(JSContext* cx, AbstractFramePtr frame,
     547             :                                      HandleFunction replacement);
     548             : 
     549             :     // For JITs.
     550             :     static size_t lambdaSlot();
     551             : };
     552             : 
     553             : // A non-syntactic dynamic scope object that captures non-lexical
     554             : // bindings. That is, a scope object that captures both qualified var
     555             : // assignments and unqualified bareword assignments. Its parent is always the
     556             : // global lexical environment.
     557             : //
     558             : // This is used in ExecuteInGlobalAndReturnScope and sits in front of the
     559             : // global scope to store 'var' bindings, and to store fresh properties created
     560             : // by assignments to undeclared variables that otherwise would have gone on
     561             : // the global object.
     562             : class NonSyntacticVariablesObject : public EnvironmentObject
     563             : {
     564             :   public:
     565             :     static const unsigned RESERVED_SLOTS = 1;
     566             :     static const Class class_;
     567             : 
     568             :     static NonSyntacticVariablesObject* create(JSContext* cx);
     569             : };
     570             : 
     571             : // With environment objects on the run-time environment chain.
     572             : class WithEnvironmentObject : public EnvironmentObject
     573             : {
     574             :     static const unsigned OBJECT_SLOT = 1;
     575             :     static const unsigned THIS_SLOT = 2;
     576             :     static const unsigned SCOPE_SLOT = 3;
     577             : 
     578             :   public:
     579             :     static const unsigned RESERVED_SLOTS = 4;
     580             :     static const Class class_;
     581             : 
     582             :     static WithEnvironmentObject* create(JSContext* cx, HandleObject object, HandleObject enclosing,
     583             :                                          Handle<WithScope*> scope);
     584             :     static WithEnvironmentObject* createNonSyntactic(JSContext* cx, HandleObject object,
     585             :                                                      HandleObject enclosing);
     586             : 
     587             :     /* Return the 'o' in 'with (o)'. */
     588             :     JSObject& object() const;
     589             : 
     590             :     /* Return object for GetThisValue. */
     591             :     JSObject* withThis() const;
     592             : 
     593             :     /*
     594             :      * Return whether this object is a syntactic with object.  If not, this is
     595             :      * a With object we inserted between the outermost syntactic scope and the
     596             :      * global object to wrap the environment chain someone explicitly passed
     597             :      * via JSAPI to CompileFunction or script evaluation.
     598             :      */
     599             :     bool isSyntactic() const;
     600             : 
     601             :     // For syntactic with environment objects, the with scope.
     602             :     WithScope& scope() const;
     603             : 
     604           0 :     static inline size_t objectSlot() {
     605           0 :         return OBJECT_SLOT;
     606             :     }
     607             : 
     608           0 :     static inline size_t thisSlot() {
     609           0 :         return THIS_SLOT;
     610             :     }
     611             : };
     612             : 
     613             : // Internal scope object used by JSOP_BINDNAME upon encountering an
     614             : // uninitialized lexical slot or an assignment to a 'const' binding.
     615             : //
     616             : // ES6 lexical bindings cannot be accessed in any way (throwing
     617             : // ReferenceErrors) until initialized. Normally, NAME operations
     618             : // unconditionally check for uninitialized lexical slots. When getting or
     619             : // looking up names, this can be done without slowing down normal operations
     620             : // on the return value. When setting names, however, we do not want to pollute
     621             : // all set-property paths with uninitialized lexical checks. For setting names
     622             : // (i.e. JSOP_SETNAME), we emit an accompanying, preceding JSOP_BINDNAME which
     623             : // finds the right scope on which to set the name. Moreover, when the name on
     624             : // the scope is an uninitialized lexical, we cannot throw eagerly, as the spec
     625             : // demands that the error be thrown after evaluating the RHS of
     626             : // assignments. Instead, this sentinel scope object is pushed on the stack.
     627             : // Attempting to access anything on this scope throws the appropriate
     628             : // ReferenceError.
     629             : //
     630             : // ES6 'const' bindings induce a runtime error when assigned to outside
     631             : // of initialization, regardless of strictness.
     632             : class RuntimeLexicalErrorObject : public EnvironmentObject
     633             : {
     634             :     static const unsigned ERROR_SLOT = 1;
     635             : 
     636             :   public:
     637             :     static const unsigned RESERVED_SLOTS = 2;
     638             :     static const Class class_;
     639             : 
     640             :     static RuntimeLexicalErrorObject* create(JSContext* cx, HandleObject enclosing,
     641             :                                              unsigned errorNumber);
     642             : 
     643           0 :     unsigned errorNumber() {
     644           0 :         return getReservedSlot(ERROR_SLOT).toInt32();
     645             :     }
     646             : };
     647             : 
     648             : 
     649             : /*****************************************************************************/
     650             : 
     651             : // A environment iterator describes the active environments starting from an
     652             : // environment, scope pair. This pair may be derived from the current point of
     653             : // execution in a frame. If derived in such a fashion, the EnvironmentIter
     654             : // tracks whether the current scope is within the extent of this initial
     655             : // frame.  Here, "frame" means a single activation of: a function, eval, or
     656             : // global code.
     657       14330 : class MOZ_RAII EnvironmentIter
     658             : {
     659             :     Rooted<ScopeIter> si_;
     660             :     RootedObject env_;
     661             :     AbstractFramePtr frame_;
     662             : 
     663             :     void incrementScopeIter();
     664             :     void settle();
     665             : 
     666             :     // No value semantics.
     667             :     EnvironmentIter(const EnvironmentIter& ei) = delete;
     668             : 
     669             :   public:
     670             :     // Constructing from a copy of an existing EnvironmentIter.
     671             :     EnvironmentIter(JSContext* cx, const EnvironmentIter& ei
     672             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
     673             : 
     674             :     // Constructing from an environment, scope pair. All environments
     675             :     // considered not to be withinInitialFrame, since no frame is given.
     676             :     EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope
     677             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
     678             : 
     679             :     // Constructing from a frame. Places the EnvironmentIter on the innermost
     680             :     // environment at pc.
     681             :     EnvironmentIter(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc
     682             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
     683             : 
     684             :     // Constructing from an environment, scope and frame. The frame is given
     685             :     // to initialize to proper enclosing environment/scope.
     686             :     EnvironmentIter(JSContext* cx, JSObject* env, Scope* scope, AbstractFramePtr frame
     687             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
     688             : 
     689             : 
     690          40 :     bool done() const {
     691          40 :         return si_.done();
     692             :     }
     693             : 
     694          40 :     explicit operator bool() const {
     695          40 :         return !done();
     696             :     }
     697             : 
     698       14899 :     void operator++(int) {
     699       14899 :         if (hasAnyEnvironmentObject())
     700        3348 :             env_ = &env_->as<EnvironmentObject>().enclosingEnvironment();
     701       14899 :         incrementScopeIter();
     702       14899 :         settle();
     703       14899 :     }
     704             : 
     705           0 :     EnvironmentIter& operator++() {
     706           0 :         operator++(1);
     707           0 :         return *this;
     708             :     }
     709             : 
     710             :     // If done():
     711             :     JSObject& enclosingEnvironment() const;
     712             : 
     713             :     // If !done():
     714             :     bool hasNonSyntacticEnvironmentObject() const;
     715             : 
     716       42138 :     bool hasSyntacticEnvironment() const {
     717       42138 :         return si_.hasSyntacticEnvironment();
     718             :     }
     719             : 
     720       14933 :     bool hasAnyEnvironmentObject() const {
     721       14933 :         return hasNonSyntacticEnvironmentObject() || hasSyntacticEnvironment();
     722             :     }
     723             : 
     724          34 :     EnvironmentObject& environment() const {
     725          34 :         MOZ_ASSERT(hasAnyEnvironmentObject());
     726          34 :         return env_->as<EnvironmentObject>();
     727             :     }
     728             : 
     729       27929 :     Scope& scope() const {
     730       27929 :         return *si_.scope();
     731             :     }
     732             : 
     733        1995 :     Scope* maybeScope() const {
     734        1995 :         if (si_)
     735        1995 :             return si_.scope();
     736           0 :         return nullptr;
     737             :     }
     738             : 
     739             :     JSFunction& callee() const {
     740             :         return env_->as<CallObject>().callee();
     741             :     }
     742             : 
     743       34504 :     bool withinInitialFrame() const {
     744       34504 :         return !!frame_;
     745             :     }
     746             : 
     747        5419 :     AbstractFramePtr initialFrame() const {
     748        5419 :         MOZ_ASSERT(withinInitialFrame());
     749        5419 :         return frame_;
     750             :     }
     751             : 
     752           0 :     AbstractFramePtr maybeInitialFrame() const {
     753           0 :         return frame_;
     754             :     }
     755             : 
     756             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     757             : };
     758             : 
     759             : // The key in MissingEnvironmentMap. For live frames, maps live frames to
     760             : // their synthesized environments. For completely optimized-out environments,
     761             : // maps the Scope to their synthesized environments. The env we synthesize for
     762             : // Scopes are read-only, and we never use their parent links, so they don't
     763             : // need to be distinct.
     764             : //
     765             : // That is, completely optimized out environments can't be distinguished by
     766             : // frame. Note that even if the frame corresponding to the Scope is live on
     767             : // the stack, it is unsound to synthesize an environment from that live
     768             : // frame. In other words, the provenance of the environment chain is from
     769             : // allocated closures (i.e., allocation sites) and is irrecoverable from
     770             : // simple stack inspection (i.e., call sites).
     771             : class MissingEnvironmentKey
     772             : {
     773             :     friend class LiveEnvironmentVal;
     774             : 
     775             :     AbstractFramePtr frame_;
     776             :     Scope* scope_;
     777             : 
     778             :   public:
     779           0 :     explicit MissingEnvironmentKey(const EnvironmentIter& ei)
     780           0 :       : frame_(ei.maybeInitialFrame()),
     781           0 :         scope_(ei.maybeScope())
     782           0 :     { }
     783             : 
     784           0 :     MissingEnvironmentKey(AbstractFramePtr frame, Scope* scope)
     785           0 :       : frame_(frame),
     786           0 :         scope_(scope)
     787           0 :     { }
     788             : 
     789           0 :     AbstractFramePtr frame() const { return frame_; }
     790           0 :     Scope* scope() const { return scope_; }
     791             : 
     792           0 :     void updateScope(Scope* scope) { scope_ = scope; }
     793           0 :     void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
     794             : 
     795             :     // For use as hash policy.
     796             :     typedef MissingEnvironmentKey Lookup;
     797             :     static HashNumber hash(MissingEnvironmentKey sk);
     798             :     static bool match(MissingEnvironmentKey sk1, MissingEnvironmentKey sk2);
     799             :     bool operator!=(const MissingEnvironmentKey& other) const {
     800             :         return frame_ != other.frame_ || scope_ != other.scope_;
     801             :     }
     802           0 :     static void rekey(MissingEnvironmentKey& k, const MissingEnvironmentKey& newKey) {
     803           0 :         k = newKey;
     804           0 :     }
     805             : };
     806             : 
     807             : // The value in LiveEnvironmentMap, mapped from by live environment objects.
     808           0 : class LiveEnvironmentVal
     809             : {
     810             :     friend class DebugEnvironments;
     811             :     friend class MissingEnvironmentKey;
     812             : 
     813             :     AbstractFramePtr frame_;
     814             :     HeapPtr<Scope*> scope_;
     815             : 
     816             :     static void staticAsserts();
     817             : 
     818             :   public:
     819           0 :     explicit LiveEnvironmentVal(const EnvironmentIter& ei)
     820           0 :       : frame_(ei.initialFrame()),
     821           0 :         scope_(ei.maybeScope())
     822           0 :     { }
     823             : 
     824           0 :     AbstractFramePtr frame() const { return frame_; }
     825             :     Scope* scope() const { return scope_; }
     826             : 
     827           0 :     void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
     828             : 
     829             :     bool needsSweep();
     830             : };
     831             : 
     832             : 
     833             : /*****************************************************************************/
     834             : 
     835             : /*
     836             :  * Debug environment objects
     837             :  *
     838             :  * The debugger effectively turns every opcode into a potential direct eval.
     839             :  * Naively, this would require creating a EnvironmentObject for every
     840             :  * call/block scope and using JSOP_GETALIASEDVAR for every access. To optimize
     841             :  * this, the engine assumes there is no debugger and optimizes scope access
     842             :  * and creation accordingly. When the debugger wants to perform an unexpected
     843             :  * eval-in-frame (or other, similar environment-requiring operations),
     844             :  * fp->environmentChain is now incomplete.
     845             :  *
     846             :  * To resolve this, the debugger first calls GetDebugEnvironmentFor* to
     847             :  * synthesize a "debug env chain". A debug env chain is just a chain of
     848             :  * objects that fill in missing environments and protect the engine from
     849             :  * unexpected access. (The latter means that some debugger operations, like
     850             :  * redefining a lexical binding, can fail when a true eval would succeed.) To
     851             :  * do both of these things, GetDebugEnvironmentFor* creates a new proxy
     852             :  * DebugEnvironmentProxy to sit in front of every existing EnvironmentObject.
     853             :  *
     854             :  * GetDebugEnvironmentFor* ensures the invariant that the same
     855             :  * DebugEnvironmentProxy is always produced for the same underlying
     856             :  * environment (optimized or not!). This is maintained by some bookkeeping
     857             :  * information stored in DebugEnvironments.
     858             :  */
     859             : 
     860             : extern JSObject*
     861             : GetDebugEnvironmentForFunction(JSContext* cx, HandleFunction fun);
     862             : 
     863             : extern JSObject*
     864             : GetDebugEnvironmentForFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
     865             : 
     866             : extern JSObject*
     867             : GetDebugEnvironmentForGlobalLexicalEnvironment(JSContext* cx);
     868             : 
     869             : /* Provides debugger access to a environment. */
     870             : class DebugEnvironmentProxy : public ProxyObject
     871             : {
     872             :     /*
     873             :      * The enclosing environment on the dynamic environment chain. This slot is analogous
     874             :      * to the ENCLOSING_ENV_SLOT of a EnvironmentObject.
     875             :      */
     876             :     static const unsigned ENCLOSING_SLOT = 0;
     877             : 
     878             :     /*
     879             :      * NullValue or a dense array holding the unaliased variables of a function
     880             :      * frame that has been popped.
     881             :      */
     882             :     static const unsigned SNAPSHOT_SLOT = 1;
     883             : 
     884             :   public:
     885             :     static DebugEnvironmentProxy* create(JSContext* cx, EnvironmentObject& env,
     886             :                                          HandleObject enclosing);
     887             : 
     888             :     EnvironmentObject& environment() const;
     889             :     JSObject& enclosingEnvironment() const;
     890             : 
     891             :     /* May only be called for proxies to function call objects. */
     892             :     ArrayObject* maybeSnapshot() const;
     893             :     void initSnapshot(ArrayObject& snapshot);
     894             : 
     895             :     // Currently, the 'declarative' environments are function, module, and
     896             :     // lexical environments.
     897             :     bool isForDeclarative() const;
     898             : 
     899             :     // Get a property by 'id', but returns sentinel values instead of throwing
     900             :     // on exceptional cases.
     901             :     static bool getMaybeSentinelValue(JSContext* cx, Handle<DebugEnvironmentProxy*> env,
     902             :                                       HandleId id, MutableHandleValue vp);
     903             : 
     904             :     // Returns true iff this is a function environment with its own this-binding
     905             :     // (all functions except arrow functions and generator expression lambdas).
     906             :     bool isFunctionEnvironmentWithThis();
     907             : 
     908             :     // Does this debug environment not have a real counterpart or was never
     909             :     // live (and thus does not have a synthesized EnvironmentObject or a
     910             :     // snapshot)?
     911             :     bool isOptimizedOut() const;
     912             : };
     913             : 
     914             : /* Maintains per-compartment debug environment bookkeeping information. */
     915             : class DebugEnvironments
     916             : {
     917             :     Zone* zone_;
     918             : 
     919             :     /* The map from (non-debug) environments to debug environments. */
     920             :     ObjectWeakMap proxiedEnvs;
     921             : 
     922             :     /*
     923             :      * The map from live frames which have optimized-away environments to the
     924             :      * corresponding debug environments.
     925             :      */
     926             :     typedef HashMap<MissingEnvironmentKey,
     927             :                     ReadBarrieredDebugEnvironmentProxy,
     928             :                     MissingEnvironmentKey,
     929             :                     RuntimeAllocPolicy> MissingEnvironmentMap;
     930             :     MissingEnvironmentMap missingEnvs;
     931             : 
     932             :     /*
     933             :      * The map from environment objects of live frames to the live frame. This
     934             :      * map updated lazily whenever the debugger needs the information. In
     935             :      * between two lazy updates, liveEnvs becomes incomplete (but not invalid,
     936             :      * onPop* removes environments as they are popped). Thus, two consecutive
     937             :      * debugger lazy updates of liveEnvs need only fill in the new
     938             :      * environments.
     939             :      */
     940             :     typedef GCHashMap<ReadBarriered<JSObject*>,
     941             :                       LiveEnvironmentVal,
     942             :                       MovableCellHasher<ReadBarriered<JSObject*>>,
     943             :                       RuntimeAllocPolicy> LiveEnvironmentMap;
     944             :     LiveEnvironmentMap liveEnvs;
     945             : 
     946             :   public:
     947             :     DebugEnvironments(JSContext* cx, Zone* zone);
     948             :     ~DebugEnvironments();
     949             : 
     950             :     Zone* zone() const { return zone_; }
     951             : 
     952             :   private:
     953             :     bool init();
     954             : 
     955             :     static DebugEnvironments* ensureCompartmentData(JSContext* cx);
     956             : 
     957             :     template <typename Environment, typename Scope>
     958             :     static void onPopGeneric(JSContext* cx, const EnvironmentIter& ei);
     959             : 
     960             :   public:
     961             :     void trace(JSTracer* trc);
     962             :     void sweep(JSRuntime* rt);
     963             :     void finish();
     964             : #ifdef JS_GC_ZEAL
     965             :     void checkHashTablesAfterMovingGC(JSRuntime* rt);
     966             : #endif
     967             : 
     968             :     // If a live frame has a synthesized entry in missingEnvs, make sure it's not
     969             :     // collected.
     970             :     void traceLiveFrame(JSTracer* trc, AbstractFramePtr frame);
     971             : 
     972             :     static DebugEnvironmentProxy* hasDebugEnvironment(JSContext* cx, EnvironmentObject& env);
     973             :     static bool addDebugEnvironment(JSContext* cx, Handle<EnvironmentObject*> env,
     974             :                                     Handle<DebugEnvironmentProxy*> debugEnv);
     975             : 
     976             :     static DebugEnvironmentProxy* hasDebugEnvironment(JSContext* cx, const EnvironmentIter& ei);
     977             :     static bool addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
     978             :                                     Handle<DebugEnvironmentProxy*> debugEnv);
     979             : 
     980             :     static bool updateLiveEnvironments(JSContext* cx);
     981             :     static LiveEnvironmentVal* hasLiveEnvironment(EnvironmentObject& env);
     982             :     static void unsetPrevUpToDateUntil(JSContext* cx, AbstractFramePtr frame);
     983             : 
     984             :     // When a frame bails out from Ion to Baseline, there might be missing
     985             :     // envs keyed on, and live envs containing, the old
     986             :     // RematerializedFrame. Forward those values to the new BaselineFrame.
     987             :     static void forwardLiveFrame(JSContext* cx, AbstractFramePtr from, AbstractFramePtr to);
     988             : 
     989             :     // When an environment is popped, we store a snapshot of its bindings that
     990             :     // live on the frame.
     991             :     //
     992             :     // This is done during frame unwinding, which cannot handle errors
     993             :     // gracefully. Errors result in no snapshot being set on the
     994             :     // DebugEnvironmentProxy.
     995             :     static void takeFrameSnapshot(JSContext* cx, Handle<DebugEnvironmentProxy*> debugEnv,
     996             :                                   AbstractFramePtr frame);
     997             : 
     998             :     // In debug-mode, these must be called whenever exiting a scope that might
     999             :     // have stack-allocated locals.
    1000             :     static void onPopCall(JSContext* cx, AbstractFramePtr frame);
    1001             :     static void onPopVar(JSContext* cx, const EnvironmentIter& ei);
    1002             :     static void onPopVar(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
    1003             :     static void onPopLexical(JSContext* cx, const EnvironmentIter& ei);
    1004             :     static void onPopLexical(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
    1005             :     static void onPopWith(AbstractFramePtr frame);
    1006             :     static void onCompartmentUnsetIsDebuggee(JSCompartment* c);
    1007             : };
    1008             : 
    1009             : }  /* namespace js */
    1010             : 
    1011             : template <>
    1012             : inline bool
    1013      292233 : JSObject::is<js::EnvironmentObject>() const
    1014             : {
    1015      557199 :     return is<js::CallObject>() ||
    1016      528935 :            is<js::VarEnvironmentObject>() ||
    1017      527938 :            is<js::ModuleEnvironmentObject>() ||
    1018      527938 :            is<js::WasmFunctionCallObject>() ||
    1019      351389 :            is<js::LexicalEnvironmentObject>() ||
    1020      157677 :            is<js::WithEnvironmentObject>() ||
    1021      427719 :            is<js::NonSyntacticVariablesObject>() ||
    1022      357462 :            is<js::RuntimeLexicalErrorObject>();
    1023             : }
    1024             : 
    1025             : template<>
    1026             : bool
    1027             : JSObject::is<js::DebugEnvironmentProxy>() const;
    1028             : 
    1029             : namespace js {
    1030             : 
    1031             : inline bool
    1032       36549 : IsSyntacticEnvironment(JSObject* env)
    1033             : {
    1034       36549 :     if (!env->is<EnvironmentObject>())
    1035        3226 :         return false;
    1036             : 
    1037       33323 :     if (env->is<WithEnvironmentObject>())
    1038        1036 :         return env->as<WithEnvironmentObject>().isSyntactic();
    1039             : 
    1040       32287 :     if (env->is<LexicalEnvironmentObject>())
    1041       26276 :         return env->as<LexicalEnvironmentObject>().isSyntactic();
    1042             : 
    1043        6011 :     if (env->is<NonSyntacticVariablesObject>())
    1044         369 :         return false;
    1045             : 
    1046        5642 :     return true;
    1047             : }
    1048             : 
    1049             : inline bool
    1050         825 : IsExtensibleLexicalEnvironment(JSObject* env)
    1051             : {
    1052        1650 :     return env->is<LexicalEnvironmentObject>() &&
    1053        1650 :            env->as<LexicalEnvironmentObject>().isExtensible();
    1054             : }
    1055             : 
    1056             : inline bool
    1057       11933 : IsGlobalLexicalEnvironment(JSObject* env)
    1058             : {
    1059       23866 :     return env->is<LexicalEnvironmentObject>() &&
    1060       23866 :            env->as<LexicalEnvironmentObject>().isGlobal();
    1061             : }
    1062             : 
    1063             : inline JSObject*
    1064         752 : MaybeUnwrapWithEnvironment(JSObject* env)
    1065             : {
    1066         752 :     if (env->is<WithEnvironmentObject>())
    1067           6 :         return &env->as<WithEnvironmentObject>().object();
    1068         746 :     return env;
    1069             : }
    1070             : 
    1071             : template <typename SpecificEnvironment>
    1072             : inline bool
    1073        5764 : IsFrameInitialEnvironment(AbstractFramePtr frame, SpecificEnvironment& env)
    1074             : {
    1075             :     // A frame's initial environment is the innermost environment
    1076             :     // corresponding to the scope chain from frame.script()->bodyScope() to
    1077             :     // frame.script()->outermostScope(). This environment must be on the chain
    1078             :     // for the frame to be considered initialized. That is, it must be on the
    1079             :     // chain for the environment chain to fully match the scope chain at the
    1080             :     // start of execution in the frame.
    1081             :     //
    1082             :     // This logic must be in sync with the HAS_INITIAL_ENV logic in
    1083             :     // InitFromBailout.
    1084             : 
    1085             :     // A function frame's CallObject, if present, is always the initial
    1086             :     // environment.
    1087             :     if (mozilla::IsSame<SpecificEnvironment, CallObject>::value)
    1088        4253 :         return true;
    1089             : 
    1090             :     // For an eval frame, the VarEnvironmentObject, if present, is always the
    1091             :     // initial environment.
    1092        1511 :     if (mozilla::IsSame<SpecificEnvironment, VarEnvironmentObject>::value &&
    1093             :         frame.isEvalFrame())
    1094             :     {
    1095           2 :         return true;
    1096             :     }
    1097             : 
    1098             :     // For named lambda frames without CallObjects (i.e., no binding in the
    1099             :     // body of the function was closed over), the LexicalEnvironmentObject
    1100             :     // corresponding to the named lambda scope is the initial environment.
    1101        1509 :     if (mozilla::IsSame<SpecificEnvironment, NamedLambdaObject>::value &&
    1102           4 :         frame.isFunctionFrame() &&
    1103           4 :         frame.callee()->needsNamedLambdaEnvironment() &&
    1104           2 :         !frame.callee()->needsCallObject())
    1105             :     {
    1106           0 :         LexicalScope* namedLambdaScope = frame.script()->maybeNamedLambdaScope();
    1107           0 :         return &env.template as<LexicalEnvironmentObject>().scope() == namedLambdaScope;
    1108             :     }
    1109             : 
    1110        1509 :     return false;
    1111             : }
    1112             : 
    1113             : extern bool
    1114             : CreateObjectsForEnvironmentChain(JSContext* cx, AutoObjectVector& chain,
    1115             :                                  HandleObject terminatingEnv,
    1116             :                                  MutableHandleObject envObj);
    1117             : 
    1118             : ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
    1119             : 
    1120             : MOZ_MUST_USE bool
    1121             : GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr frame,
    1122             :                                          jsbytecode* pc, MutableHandleValue res);
    1123             : 
    1124             : MOZ_MUST_USE bool
    1125             : CheckVarNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
    1126             :                      HandlePropertyName name);
    1127             : 
    1128             : MOZ_MUST_USE bool
    1129             : CheckCanDeclareGlobalBinding(JSContext* cx, Handle<GlobalObject*> global,
    1130             :                              HandlePropertyName name, bool isFunction);
    1131             : 
    1132             : MOZ_MUST_USE bool
    1133             : CheckLexicalNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
    1134             :                          HandleObject varObj, HandlePropertyName name);
    1135             : 
    1136             : MOZ_MUST_USE bool
    1137             : CheckGlobalDeclarationConflicts(JSContext* cx, HandleScript script,
    1138             :                                 Handle<LexicalEnvironmentObject*> lexicalEnv,
    1139             :                                 HandleObject varObj);
    1140             : 
    1141             : MOZ_MUST_USE bool
    1142             : CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script, HandleObject envChain,
    1143             :                               HandleObject varObj);
    1144             : 
    1145             : MOZ_MUST_USE bool
    1146             : InitFunctionEnvironmentObjects(JSContext* cx, AbstractFramePtr frame);
    1147             : 
    1148             : MOZ_MUST_USE bool
    1149             : PushVarEnvironmentObject(JSContext* cx, HandleScope scope, AbstractFramePtr frame);
    1150             : 
    1151             : MOZ_MUST_USE bool
    1152             : GetFrameEnvironmentAndScope(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc,
    1153             :                             MutableHandleObject env, MutableHandleScope scope);
    1154             : 
    1155             : #ifdef DEBUG
    1156             : bool
    1157             : AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
    1158             : #endif
    1159             : 
    1160             : } // namespace js
    1161             : 
    1162             : namespace JS {
    1163             : 
    1164             : template <>
    1165             : struct DeletePolicy<js::DebugEnvironments> : public js::GCManagedDeletePolicy<js::DebugEnvironments>
    1166             : {};
    1167             : 
    1168             : } // namespace JS
    1169             : 
    1170             : #endif /* vm_EnvironmentObject_h */

Generated by: LCOV version 1.13