Home | History | Annotate | Download | only in parsing
      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 
     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 
     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 
     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 
     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