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