1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef vm_BindingKind_h
8 #define vm_BindingKind_h
9 
10 #include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_ASSERT_IF
11 #include "mozilla/Casting.h"     // mozilla::AssertedCast
12 
13 #include <stdint.h>  // uint16_t, uint32_t
14 
15 #include "vm/BytecodeUtil.h"  // LOCALNO_LIMIT, ENVCOORD_SLOT_LIMIT
16 
17 namespace js {
18 
19 enum class BindingKind : uint8_t {
20   Import,
21   FormalParameter,
22   Var,
23   Let,
24   Const,
25 
26   // So you think named lambda callee names are consts? Nope! They don't
27   // throw when being assigned to in sloppy mode.
28   NamedLambdaCallee,
29 
30   // ClassBodyScope bindings that aren't bindings in the spec, but are put into
31   // a scope as an implementation detail: `.privateBrand`,
32   // `.staticInitializers`, private names, and private accessor functions.
33   Synthetic,
34 
35   // ClassBodyScope binding that stores the function object for a non-static
36   // private method.
37   PrivateMethod,
38 };
39 
BindingKindIsLexical(BindingKind kind)40 static inline bool BindingKindIsLexical(BindingKind kind) {
41   return kind == BindingKind::Let || kind == BindingKind::Const;
42 }
43 
44 class BindingLocation {
45  public:
46   enum class Kind {
47     Global,
48     Argument,
49     Frame,
50     Environment,
51     Import,
52     NamedLambdaCallee
53   };
54 
55  private:
56   Kind kind_;
57   uint32_t slot_;
58 
BindingLocation(Kind kind,uint32_t slot)59   BindingLocation(Kind kind, uint32_t slot) : kind_(kind), slot_(slot) {}
60 
61  public:
Global()62   static BindingLocation Global() {
63     return BindingLocation(Kind::Global, UINT32_MAX);
64   }
65 
Argument(uint16_t slot)66   static BindingLocation Argument(uint16_t slot) {
67     return BindingLocation(Kind::Argument, slot);
68   }
69 
Frame(uint32_t slot)70   static BindingLocation Frame(uint32_t slot) {
71     MOZ_ASSERT(slot < LOCALNO_LIMIT);
72     return BindingLocation(Kind::Frame, slot);
73   }
74 
Environment(uint32_t slot)75   static BindingLocation Environment(uint32_t slot) {
76     MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
77     return BindingLocation(Kind::Environment, slot);
78   }
79 
Import()80   static BindingLocation Import() {
81     return BindingLocation(Kind::Import, UINT32_MAX);
82   }
83 
NamedLambdaCallee()84   static BindingLocation NamedLambdaCallee() {
85     return BindingLocation(Kind::NamedLambdaCallee, UINT32_MAX);
86   }
87 
88   bool operator==(const BindingLocation& other) const {
89     return kind_ == other.kind_ && slot_ == other.slot_;
90   }
91 
92   bool operator!=(const BindingLocation& other) const {
93     return !operator==(other);
94   }
95 
kind()96   Kind kind() const { return kind_; }
97 
slot()98   uint32_t slot() const {
99     MOZ_ASSERT(kind_ == Kind::Frame || kind_ == Kind::Environment);
100     return slot_;
101   }
102 
argumentSlot()103   uint16_t argumentSlot() const {
104     MOZ_ASSERT(kind_ == Kind::Argument);
105     return mozilla::AssertedCast<uint16_t>(slot_);
106   }
107 };
108 
109 }  // namespace js
110 
111 #endif  // vm_BindingKind_h
112