// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/parsing/preparsed-scope-data.h" #include "src/ast/scopes.h" #include "src/ast/variables.h" #include "src/objects-inl.h" namespace v8 { namespace internal { bool PreParsedScopeData::HasVariablesWhichNeedAllocationData(Scope* scope) { if (!scope->is_hidden()) { for (Variable* var : *scope->locals()) { if (var->mode() == VAR || var->mode() == LET || var->mode() == CONST) { return true; } } } for (Scope* inner = scope->inner_scope(); inner != nullptr; inner = inner->sibling()) { if (HasVariablesWhichNeedAllocationData(inner)) { return true; } } return false; } PreParsedScopeData::ScopeScope::ScopeScope(PreParsedScopeData* data, ScopeType scope_type, int start_position, int end_position) : data_(data), previous_scope_(data->current_scope_) { data->current_scope_ = this; data->backing_store_.push_back(scope_type); data->backing_store_.push_back(start_position); data->backing_store_.push_back(end_position); // Reserve space for variable and inner scope count (we don't know yet how // many will be added). index_in_data_ = data->backing_store_.size(); data->backing_store_.push_back(-1); data->backing_store_.push_back(-1); } PreParsedScopeData::ScopeScope::~ScopeScope() { data_->current_scope_ = previous_scope_; if (got_data_) { DCHECK_GT(variable_count_ + inner_scope_count_, 0); if (previous_scope_ != nullptr) { previous_scope_->got_data_ = true; ++previous_scope_->inner_scope_count_; } data_->backing_store_[index_in_data_] = inner_scope_count_; data_->backing_store_[index_in_data_ + 1] = variable_count_; } else { // No interesting data for this scope (or its children); remove from the // data. DCHECK_EQ(data_->backing_store_.size(), index_in_data_ + 2); DCHECK_GE(index_in_data_, 3); DCHECK_EQ(variable_count_, 0); data_->backing_store_.erase( data_->backing_store_.begin() + index_in_data_ - 3, data_->backing_store_.end()); } } void PreParsedScopeData::ScopeScope::MaybeAddVariable(Variable* var) { if (var->mode() == VAR || var->mode() == LET || var->mode() == CONST) { #ifdef DEBUG // For tests (which check that the data is about the same variables). const AstRawString* name = var->raw_name(); data_->backing_store_.push_back(name->length()); for (int i = 0; i < name->length(); ++i) { data_->backing_store_.push_back(name->raw_data()[i]); } #endif data_->backing_store_.push_back(var->location()); data_->backing_store_.push_back(var->maybe_assigned()); ++variable_count_; got_data_ = true; } } } // namespace internal } // namespace v8