LCOV - code coverage report
Current view: top level - js/src/frontend - NameAnalysisTypes.h (source / functions) Hit Total Coverage
Test: output.info Lines: 103 114 90.4 %
Date: 2017-07-14 16:53:18 Functions: 34 37 91.9 %
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_NameAnalysis_h
       8             : #define frontend_NameAnalysis_h
       9             : 
      10             : #include "jsopcode.h"
      11             : 
      12             : #include "vm/Scope.h"
      13             : 
      14             : namespace js {
      15             : 
      16             : // An "environment coordinate" describes how to get from head of the
      17             : // environment chain to a given lexically-enclosing variable. An environment
      18             : // coordinate has two dimensions:
      19             : //  - hops: the number of environment objects on the scope chain to skip
      20             : //  - slot: the slot on the environment object holding the variable's value
      21             : class EnvironmentCoordinate
      22             : {
      23             :     uint32_t hops_;
      24             :     uint32_t slot_;
      25             : 
      26             :     // Technically, hops_/slot_ are ENVCOORD_(HOPS|SLOT)_BITS wide.  Since
      27             :     // EnvironmentCoordinate is a temporary value, don't bother with a bitfield as
      28             :     // this only adds overhead.
      29             :     static_assert(ENVCOORD_HOPS_BITS <= 32, "We have enough bits below");
      30             :     static_assert(ENVCOORD_SLOT_BITS <= 32, "We have enough bits below");
      31             : 
      32             :   public:
      33       13299 :     explicit inline EnvironmentCoordinate(jsbytecode* pc)
      34       13299 :       : hops_(GET_ENVCOORD_HOPS(pc)), slot_(GET_ENVCOORD_SLOT(pc + ENVCOORD_HOPS_LEN))
      35             :     {
      36       13299 :         MOZ_ASSERT(JOF_OPTYPE(JSOp(*pc)) == JOF_ENVCOORD);
      37       13299 :     }
      38             : 
      39        8054 :     EnvironmentCoordinate() {}
      40             : 
      41        8054 :     void setHops(uint32_t hops) {
      42        8054 :         MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT);
      43        8054 :         hops_ = hops;
      44        8054 :     }
      45             : 
      46        8054 :     void setSlot(uint32_t slot) {
      47        8054 :         MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
      48        8054 :         slot_ = slot;
      49        8054 :     }
      50             : 
      51       20394 :     uint32_t hops() const {
      52       20394 :         MOZ_ASSERT(hops_ < ENVCOORD_HOPS_LIMIT);
      53       20394 :         return hops_;
      54             :     }
      55             : 
      56       20345 :     uint32_t slot() const {
      57       20345 :         MOZ_ASSERT(slot_ < ENVCOORD_SLOT_LIMIT);
      58       20345 :         return slot_;
      59             :     }
      60             : 
      61           2 :     bool operator==(const EnvironmentCoordinate& rhs) const {
      62           2 :         return hops() == rhs.hops() && slot() == rhs.slot();
      63             :     }
      64             : };
      65             : 
      66             : namespace frontend {
      67             : 
      68             : // A detailed kind used for tracking declarations in the Parser. Used for
      69             : // specific early error semantics and better error messages.
      70             : enum class DeclarationKind : uint8_t
      71             : {
      72             :     PositionalFormalParameter,
      73             :     FormalParameter,
      74             :     CoverArrowParameter,
      75             :     Var,
      76             :     ForOfVar,
      77             :     Let,
      78             :     Const,
      79             :     Import,
      80             :     BodyLevelFunction,
      81             :     ModuleBodyLevelFunction,
      82             :     LexicalFunction,
      83             :     SloppyLexicalFunction,
      84             :     VarForAnnexBLexicalFunction,
      85             :     SimpleCatchParameter,
      86             :     CatchParameter
      87             : };
      88             : 
      89             : static inline BindingKind
      90       47373 : DeclarationKindToBindingKind(DeclarationKind kind)
      91             : {
      92       47373 :     switch (kind) {
      93             :       case DeclarationKind::PositionalFormalParameter:
      94             :       case DeclarationKind::FormalParameter:
      95             :       case DeclarationKind::CoverArrowParameter:
      96       12286 :         return BindingKind::FormalParameter;
      97             : 
      98             :       case DeclarationKind::Var:
      99             :       case DeclarationKind::BodyLevelFunction:
     100             :       case DeclarationKind::ModuleBodyLevelFunction:
     101             :       case DeclarationKind::VarForAnnexBLexicalFunction:
     102             :       case DeclarationKind::ForOfVar:
     103       18198 :         return BindingKind::Var;
     104             : 
     105             :       case DeclarationKind::Let:
     106             :       case DeclarationKind::LexicalFunction:
     107             :       case DeclarationKind::SloppyLexicalFunction:
     108             :       case DeclarationKind::SimpleCatchParameter:
     109             :       case DeclarationKind::CatchParameter:
     110       13410 :         return BindingKind::Let;
     111             : 
     112             :       case DeclarationKind::Const:
     113        3479 :         return BindingKind::Const;
     114             : 
     115             :       case DeclarationKind::Import:
     116           0 :         return BindingKind::Import;
     117             :     }
     118             : 
     119           0 :     MOZ_CRASH("Bad DeclarationKind");
     120             : }
     121             : 
     122             : static inline bool
     123        3001 : DeclarationKindIsLexical(DeclarationKind kind)
     124             : {
     125        3001 :     return BindingKindIsLexical(DeclarationKindToBindingKind(kind));
     126             : }
     127             : 
     128             : // Used in Parser to track declared names.
     129             : class DeclaredNameInfo
     130             : {
     131             :     uint32_t pos_;
     132             :     DeclarationKind kind_;
     133             : 
     134             :     // If the declared name is a binding, whether the binding is closed
     135             :     // over. Its value is meaningless if the declared name is not a binding
     136             :     // (i.e., a 'var' declared name in a non-var scope).
     137             :     bool closedOver_;
     138             : 
     139             :   public:
     140       29316 :     explicit DeclaredNameInfo(DeclarationKind kind, uint32_t pos)
     141       29316 :       : pos_(pos),
     142             :         kind_(kind),
     143       29316 :         closedOver_(false)
     144       29316 :     { }
     145             : 
     146             :     // Needed for InlineMap.
     147             :     DeclaredNameInfo() = default;
     148             : 
     149       55131 :     DeclarationKind kind() const {
     150       55131 :         return kind_;
     151             :     }
     152             : 
     153             :     static const uint32_t npos = uint32_t(-1);
     154             : 
     155         655 :     uint32_t pos() const {
     156         655 :         return pos_;
     157             :     }
     158             : 
     159           0 :     void alterKind(DeclarationKind kind) {
     160           0 :         kind_ = kind;
     161           0 :     }
     162             : 
     163        1503 :     void setClosedOver() {
     164        1503 :         closedOver_ = true;
     165        1503 :     }
     166             : 
     167       41986 :     bool closedOver() const {
     168       41986 :         return closedOver_;
     169             :     }
     170             : };
     171             : 
     172             : // Used in BytecodeEmitter to map names to locations.
     173             : class NameLocation
     174             : {
     175             :   public:
     176             :     enum class Kind : uint8_t
     177             :     {
     178             :         // Cannot statically determine where the name lives. Needs to walk the
     179             :         // environment chain to search for the name.
     180             :         Dynamic,
     181             : 
     182             :         // The name lives on the global or is a global lexical binding. Search
     183             :         // for the name on the global scope.
     184             :         Global,
     185             : 
     186             :         // Special mode used only when emitting self-hosted scripts. See
     187             :         // BytecodeEmitter::lookupName.
     188             :         Intrinsic,
     189             : 
     190             :         // In a named lambda, the name is the callee itself.
     191             :         NamedLambdaCallee,
     192             : 
     193             :         // The name is a positional formal parameter name and can be retrieved
     194             :         // directly from the stack using slot_.
     195             :         ArgumentSlot,
     196             : 
     197             :         // The name is not closed over and lives on the frame in slot_.
     198             :         FrameSlot,
     199             : 
     200             :         // The name is closed over and lives on an environment hops_ away in slot_.
     201             :         EnvironmentCoordinate,
     202             : 
     203             :         // An imported name in a module.
     204             :         Import,
     205             : 
     206             :         // Cannot statically determine where the synthesized var for Annex
     207             :         // B.3.3 lives.
     208             :         DynamicAnnexBVar
     209             :     };
     210             : 
     211             :   private:
     212             :     // Where the name lives.
     213             :     Kind kind_;
     214             : 
     215             :     // If the name is not Dynamic or DynamicAnnexBVar, the kind of the
     216             :     // binding.
     217             :     BindingKind bindingKind_;
     218             : 
     219             :     // If the name is closed over and accessed via EnvironmentCoordinate, the
     220             :     // number of dynamic environments to skip.
     221             :     //
     222             :     // Otherwise UINT8_MAX.
     223             :     uint8_t hops_;
     224             : 
     225             :     // If the name lives on the frame, the slot frame.
     226             :     //
     227             :     // If the name is closed over and accessed via EnvironmentCoordinate, the
     228             :     // slot on the environment.
     229             :     //
     230             :     // Otherwise LOCALNO_LIMIT/ENVCOORD_SLOT_LIMIT.
     231             :     uint32_t slot_ : ENVCOORD_SLOT_BITS;
     232             : 
     233             :     static_assert(LOCALNO_BITS == ENVCOORD_SLOT_BITS,
     234             :                   "Frame and environment slots must be same sized.");
     235             : 
     236       25437 :     NameLocation(Kind kind, BindingKind bindingKind,
     237             :                  uint8_t hops = UINT8_MAX, uint32_t slot = ENVCOORD_SLOT_LIMIT)
     238       25437 :       : kind_(kind),
     239             :         bindingKind_(bindingKind),
     240             :         hops_(hops),
     241       25437 :         slot_(slot)
     242       25437 :     { }
     243             : 
     244             :   public:
     245             :     // Default constructor for InlineMap.
     246          13 :     NameLocation() = default;
     247             : 
     248         803 :     static NameLocation Dynamic() {
     249         803 :         return NameLocation();
     250             :     }
     251             : 
     252        3397 :     static NameLocation Global(BindingKind bindKind) {
     253        3397 :         MOZ_ASSERT(bindKind != BindingKind::FormalParameter);
     254        3397 :         return NameLocation(Kind::Global, bindKind);
     255             :     }
     256             : 
     257           3 :     static NameLocation Intrinsic() {
     258           3 :         return NameLocation(Kind::Intrinsic, BindingKind::Var);
     259             :     }
     260             : 
     261         384 :     static NameLocation NamedLambdaCallee() {
     262         384 :         return NameLocation(Kind::NamedLambdaCallee, BindingKind::NamedLambdaCallee);
     263             :     }
     264             : 
     265        5459 :     static NameLocation ArgumentSlot(uint16_t slot) {
     266        5459 :         return NameLocation(Kind::ArgumentSlot, BindingKind::FormalParameter, 0, slot);
     267             :     }
     268             : 
     269       11260 :     static NameLocation FrameSlot(BindingKind bindKind, uint32_t slot) {
     270       11260 :         MOZ_ASSERT(slot < LOCALNO_LIMIT);
     271       11260 :         return NameLocation(Kind::FrameSlot, bindKind, 0, slot);
     272             :     }
     273             : 
     274        2219 :     static NameLocation EnvironmentCoordinate(BindingKind bindKind, uint8_t hops, uint32_t slot) {
     275        2219 :         MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
     276        2219 :         return NameLocation(Kind::EnvironmentCoordinate, bindKind, hops, slot);
     277             :     }
     278             : 
     279           0 :     static NameLocation Import() {
     280           0 :         return NameLocation(Kind::Import, BindingKind::Import);
     281             :     }
     282             : 
     283           0 :     static NameLocation DynamicAnnexBVar() {
     284           0 :         return NameLocation(Kind::DynamicAnnexBVar, BindingKind::Var);
     285             :     }
     286             : 
     287       20767 :     static NameLocation fromBinding(BindingKind bindKind, const BindingLocation& bl) {
     288       20767 :         switch (bl.kind()) {
     289             :           case BindingLocation::Kind::Global:
     290        1924 :             return Global(bindKind);
     291             :           case BindingLocation::Kind::Argument:
     292        5459 :             return ArgumentSlot(bl.argumentSlot());
     293             :           case BindingLocation::Kind::Frame:
     294       11247 :             return FrameSlot(bindKind, bl.slot());
     295             :           case BindingLocation::Kind::Environment:
     296        1753 :             return EnvironmentCoordinate(bindKind, 0, bl.slot());
     297             :           case BindingLocation::Kind::Import:
     298           0 :             return Import();
     299             :           case BindingLocation::Kind::NamedLambdaCallee:
     300         384 :             return NamedLambdaCallee();
     301             :         }
     302           0 :         MOZ_CRASH("Bad BindingKind");
     303             :     }
     304             : 
     305          15 :     bool operator==(const NameLocation& other) const {
     306          45 :         return kind_ == other.kind_ && bindingKind_ == other.bindingKind_ &&
     307          45 :                hops_ == other.hops_ && slot_ == other.slot_;
     308             :     }
     309             : 
     310             :     bool operator!=(const NameLocation& other) const {
     311             :         return !(*this == other);
     312             :     }
     313             : 
     314      138908 :     Kind kind() const {
     315      138908 :         return kind_;
     316             :     }
     317             : 
     318       14330 :     uint16_t argumentSlot() const {
     319       14330 :         MOZ_ASSERT(kind_ == Kind::ArgumentSlot);
     320       14330 :         return mozilla::AssertedCast<uint16_t>(slot_);
     321             :     }
     322             : 
     323       43134 :     uint32_t frameSlot() const {
     324       43134 :         MOZ_ASSERT(kind_ == Kind::FrameSlot);
     325       43134 :         return slot_;
     326             :     }
     327             : 
     328        2715 :     NameLocation addHops(uint8_t more) {
     329        2715 :         MOZ_ASSERT(hops_ < ENVCOORD_HOPS_LIMIT - more);
     330        2715 :         MOZ_ASSERT(kind_ == Kind::EnvironmentCoordinate);
     331        2715 :         return NameLocation(kind_, bindingKind_, hops_ + more, slot_);
     332             :     }
     333             : 
     334        8054 :     class EnvironmentCoordinate environmentCoordinate() const {
     335        8054 :         MOZ_ASSERT(kind_ == Kind::EnvironmentCoordinate);
     336        8054 :         class EnvironmentCoordinate coord;
     337        8054 :         coord.setHops(hops_);
     338        8054 :         coord.setSlot(slot_);
     339        8054 :         return coord;
     340             :     }
     341             : 
     342       68916 :     BindingKind bindingKind() const {
     343       68916 :         MOZ_ASSERT(kind_ != Kind::Dynamic);
     344       68916 :         return bindingKind_;
     345             :     }
     346             : 
     347       64679 :     bool isLexical() const {
     348       64679 :         return BindingKindIsLexical(bindingKind());
     349             :     }
     350             : 
     351         984 :     bool isConst() const {
     352         984 :         return bindingKind() == BindingKind::Const;
     353             :     }
     354             : 
     355       15250 :     bool hasKnownSlot() const {
     356       30500 :         return kind_ == Kind::ArgumentSlot ||
     357       17600 :                kind_ == Kind::FrameSlot ||
     358       17600 :                kind_ == Kind::EnvironmentCoordinate;
     359             :     }
     360             : };
     361             : 
     362             : // This type is declared here for LazyScript::Create.
     363             : using AtomVector = Vector<JSAtom*, 24, SystemAllocPolicy>;
     364             : 
     365             : } // namespace frontend
     366             : } // namespace js
     367             : 
     368             : namespace mozilla {
     369             : 
     370             : template <>
     371             : struct IsPod<js::frontend::DeclaredNameInfo> : TrueType {};
     372             : 
     373             : template <>
     374             : struct IsPod<js::frontend::NameLocation> : TrueType {};
     375             : 
     376             : } // namespace mozilla
     377             : 
     378             : #endif // frontend_NameAnalysis_h

Generated by: LCOV version 1.13