• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 #include "src/parsing/preparsed-scope-data.h"
6 
7 #include "src/ast/scopes.h"
8 #include "src/ast/variables.h"
9 #include "src/objects-inl.h"
10 
11 namespace v8 {
12 namespace internal {
13 
HasVariablesWhichNeedAllocationData(Scope * scope)14 bool PreParsedScopeData::HasVariablesWhichNeedAllocationData(Scope* scope) {
15   if (!scope->is_hidden()) {
16     for (Variable* var : *scope->locals()) {
17       if (var->mode() == VAR || var->mode() == LET || var->mode() == CONST) {
18         return true;
19       }
20     }
21   }
22   for (Scope* inner = scope->inner_scope(); inner != nullptr;
23        inner = inner->sibling()) {
24     if (HasVariablesWhichNeedAllocationData(inner)) {
25       return true;
26     }
27   }
28   return false;
29 }
30 
ScopeScope(PreParsedScopeData * data,ScopeType scope_type,int start_position,int end_position)31 PreParsedScopeData::ScopeScope::ScopeScope(PreParsedScopeData* data,
32                                            ScopeType scope_type,
33                                            int start_position, int end_position)
34     : data_(data), previous_scope_(data->current_scope_) {
35   data->current_scope_ = this;
36   data->backing_store_.push_back(scope_type);
37   data->backing_store_.push_back(start_position);
38   data->backing_store_.push_back(end_position);
39   // Reserve space for variable and inner scope count (we don't know yet how
40   // many will be added).
41   index_in_data_ = data->backing_store_.size();
42   data->backing_store_.push_back(-1);
43   data->backing_store_.push_back(-1);
44 }
45 
~ScopeScope()46 PreParsedScopeData::ScopeScope::~ScopeScope() {
47   data_->current_scope_ = previous_scope_;
48   if (got_data_) {
49     DCHECK_GT(variable_count_ + inner_scope_count_, 0);
50     if (previous_scope_ != nullptr) {
51       previous_scope_->got_data_ = true;
52       ++previous_scope_->inner_scope_count_;
53     }
54     data_->backing_store_[index_in_data_] = inner_scope_count_;
55     data_->backing_store_[index_in_data_ + 1] = variable_count_;
56   } else {
57     // No interesting data for this scope (or its children); remove from the
58     // data.
59     DCHECK_EQ(data_->backing_store_.size(), index_in_data_ + 2);
60     DCHECK_GE(index_in_data_, 3);
61     DCHECK_EQ(variable_count_, 0);
62     data_->backing_store_.erase(
63         data_->backing_store_.begin() + index_in_data_ - 3,
64         data_->backing_store_.end());
65   }
66 }
67 
MaybeAddVariable(Variable * var)68 void PreParsedScopeData::ScopeScope::MaybeAddVariable(Variable* var) {
69   if (var->mode() == VAR || var->mode() == LET || var->mode() == CONST) {
70 #ifdef DEBUG
71     // For tests (which check that the data is about the same variables).
72     const AstRawString* name = var->raw_name();
73     data_->backing_store_.push_back(name->length());
74     for (int i = 0; i < name->length(); ++i) {
75       data_->backing_store_.push_back(name->raw_data()[i]);
76     }
77 #endif
78     data_->backing_store_.push_back(var->location());
79     data_->backing_store_.push_back(var->maybe_assigned());
80     ++variable_count_;
81     got_data_ = true;
82   }
83 }
84 
85 }  // namespace internal
86 }  // namespace v8
87