• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_PARSING_FUNC_NAME_INFERRER_H_
6 #define V8_PARSING_FUNC_NAME_INFERRER_H_
7 
8 #include <vector>
9 
10 #include "src/base/macros.h"
11 #include "src/base/pointer-with-payload.h"
12 
13 namespace v8 {
14 
15 namespace internal {
16 class AstRawString;
17 }
18 
19 namespace base {
20 template <>
21 struct PointerWithPayloadTraits<v8::internal::AstRawString> {
22   static constexpr int kAvailableBits = 2;
23 };
24 }  // namespace base
25 
26 namespace internal {
27 
28 class AstConsString;
29 class AstValueFactory;
30 class FunctionLiteral;
31 
32 enum class InferName { kYes, kNo };
33 
34 // FuncNameInferrer is a stateful class that is used to perform name
35 // inference for anonymous functions during static analysis of source code.
36 // Inference is performed in cases when an anonymous function is assigned
37 // to a variable or a property (see test-func-name-inference.cc for examples.)
38 //
39 // The basic idea is that during parsing of LHSs of certain expressions
40 // (assignments, declarations, object literals) we collect name strings,
41 // and during parsing of the RHS, a function literal can be collected. After
42 // parsing the RHS we can infer a name for function literals that do not have
43 // a name.
44 class FuncNameInferrer {
45  public:
46   explicit FuncNameInferrer(AstValueFactory* ast_value_factory);
47 
48   FuncNameInferrer(const FuncNameInferrer&) = delete;
49   FuncNameInferrer& operator=(const FuncNameInferrer&) = delete;
50 
51   // To enter function name inference state, put a FuncNameInferrer::State
52   // on the stack.
53   class State {
54    public:
55     explicit State(FuncNameInferrer* fni)
56         : fni_(fni), top_(fni->names_stack_.size()) {
57       ++fni_->scope_depth_;
58     }
59     ~State() {
60       DCHECK(fni_->IsOpen());
61       fni_->names_stack_.resize(top_);
62       --fni_->scope_depth_;
63     }
64     State(const State&) = delete;
65     State& operator=(const State&) = delete;
66 
67    private:
68     FuncNameInferrer* fni_;
69     size_t top_;
70   };
71 
72   // Returns whether we have entered name collection state.
73   bool IsOpen() const { return scope_depth_ > 0; }
74 
75   // Pushes an enclosing the name of enclosing function onto names stack.
76   void PushEnclosingName(const AstRawString* name);
77 
78   // Pushes an encountered name onto names stack when in collection state.
79   void PushLiteralName(const AstRawString* name);
80 
81   void PushVariableName(const AstRawString* name);
82 
83   // Adds a function to infer name for.
84   void AddFunction(FunctionLiteral* func_to_infer) {
85     if (IsOpen()) {
86       funcs_to_infer_.push_back(func_to_infer);
87     }
88   }
89 
90   void RemoveLastFunction() {
91     if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back();
92   }
93 
94   void RemoveAsyncKeywordFromEnd();
95 
96   // Infers a function name and leaves names collection state.
97   void Infer() {
98     DCHECK(IsOpen());
99     if (!funcs_to_infer_.empty()) InferFunctionsNames();
100   }
101 
102  private:
103   enum NameType : uint8_t {
104     kEnclosingConstructorName,
105     kLiteralName,
106     kVariableName
107   };
108   struct Name {
109     // Needed for names_stack_.resize()
110     Name() { UNREACHABLE(); }
111     Name(const AstRawString* name, NameType type)
112         : name_and_type_(name, type) {}
113 
114     base::PointerWithPayload<const AstRawString, NameType, 2> name_and_type_;
115     inline const AstRawString* name() const {
116       return name_and_type_.GetPointer();
117     }
118     inline NameType type() const { return name_and_type_.GetPayload(); }
119   };
120 
121   // Constructs a full name in dotted notation from gathered names.
122   AstConsString* MakeNameFromStack();
123 
124   // Performs name inferring for added functions.
125   void InferFunctionsNames();
126 
127   AstValueFactory* ast_value_factory_;
128   std::vector<Name> names_stack_;
129   std::vector<FunctionLiteral*> funcs_to_infer_;
130   size_t scope_depth_ = 0;
131 };
132 
133 
134 }  // namespace internal
135 }  // namespace v8
136 
137 #endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
138